我知道这是一个非常基本的问题,但在用高级语言编写了几个项目之后,我刚刚开始了一些基本的c++编程。
基本上我有三个问题:
为什么使用指针而不是普通变量? 我应该在何时何地使用指针? 如何在数组中使用指针?
我知道这是一个非常基本的问题,但在用高级语言编写了几个项目之后,我刚刚开始了一些基本的c++编程。
基本上我有三个问题:
为什么使用指针而不是普通变量? 我应该在何时何地使用指针? 如何在数组中使用指针?
当前回答
指针在许多数据结构中非常重要,这些数据结构的设计要求能够有效地将一个“节点”链接到另一个“节点”。你不会“选择”指针而不是普通的数据类型,比如float,它们只是有不同的用途。
指针在需要高性能和/或紧凑内存占用的地方非常有用。
数组中第一个元素的地址可以赋值给一个指针。这允许您直接访问底层已分配的字节。数组的全部意义就是避免你需要这样做。
其他回答
为什么使用指针而不是普通变量?
简单的回答是:不要。;-)指针用于不能使用其他任何指针的地方。这要么是因为缺乏适当的功能,缺少数据类型,要么只是为了性能。更多的下面……
我应该在何时何地使用指针?
这里的简短回答是:你不能使用其他任何东西。在C语言中,你不支持复杂的数据类型,比如字符串。也没有办法将变量“通过引用”传递给函数。这就需要用到指针了。你也可以让它们指向任何东西,链表,结构体成员等等。但我们先不谈这个。
如何在数组中使用指针?
毫不费力,却充满了困惑。如果我们谈论简单的数据类型,如int和char,数组和指针之间几乎没有区别。 这些声明非常相似(但不相同——例如sizeof将返回不同的值):
char* a = "Hello";
char a[] = "Hello";
你可以像这样找到数组中的任何元素
printf("Second char is: %c", a[1]);
索引1,因为数组从元素0开始。: -)
或者你也可以这样做
printf("Second char is: %c", *(a+1));
指针操作符(*)是必需的,因为我们要告诉printf我们想打印一个字符。如果没有*,内存地址本身的字符表示将被打印出来。现在我们用字符本身代替。如果我们使用%s而不是%c,我们将要求printf打印'a' + 1所指向的内存地址的内容(在上面的例子中),并且我们不必把*放在前面:
printf("Second char is: %s", (a+1)); /* WRONG */
但这并不只是打印第二个字符,而是在下一个内存地址中打印所有字符,直到找到一个空字符(\0)。这就是事情开始变得危险的地方。如果您意外地尝试使用%s格式化程序打印类型为整型而不是char指针的变量,该怎么办?
char* a = "Hello";
int b = 120;
printf("Second char is: %s", b);
This would print whatever is found on memory address 120 and go on printing until a null character was found. It is wrong and illegal to perform this printf statement, but it would probably work anyway, since a pointer actually is of the type int in many environments. Imagine the problems you might cause if you were to use sprintf() instead and assign this way too long "char array" to another variable, that only got a certain limited space allocated. You would most likely end up writing over something else in the memory and cause your program to crash (if you are lucky).
哦,如果你在声明char数组/指针时没有给它赋一个字符串值,你必须在给它赋值之前给它分配足够的内存。使用malloc, calloc或类似的。这是因为你只在数组中声明了一个元素/一个内存地址。这里有几个例子:
char* x;
/* Allocate 6 bytes of memory for me and point x to the first of them. */
x = (char*) malloc(6);
x[0] = 'H';
x[1] = 'e';
x[2] = 'l';
x[3] = 'l';
x[4] = 'o';
x[5] = '\0';
printf("String \"%s\" at address: %d\n", x, x);
/* Delete the allocation (reservation) of the memory. */
/* The char pointer x is still pointing to this address in memory though! */
free(x);
/* Same as malloc but here the allocated space is filled with null characters!*/
x = (char *) calloc(6, sizeof(x));
x[0] = 'H';
x[1] = 'e';
x[2] = 'l';
x[3] = 'l';
x[4] = 'o';
x[5] = '\0';
printf("String \"%s\" at address: %d\n", x, x);
/* And delete the allocation again... */
free(x);
/* We can set the size at declaration time as well */
char xx[6];
xx[0] = 'H';
xx[1] = 'e';
xx[2] = 'l';
xx[3] = 'l';
xx[4] = 'o';
xx[5] = '\0';
printf("String \"%s\" at address: %d\n", xx, xx);
请注意,在对分配的内存执行free()后,仍然可以使用变量x,但您不知道其中有什么。还要注意,两个printf()可能会给您不同的地址,因为不能保证第二次内存分配是在与第一次相同的空间中执行的。
这里描述了C语言中指针的需求
其基本思想是,语言中的许多限制(如使用数组、字符串和修改函数中的多个变量)可以通过操纵数据的内存位置来消除。为了克服这些限制,C语言中引入了指针。
此外,还可以看到,使用指针,您可以更快地运行代码,并在将大数据类型(如具有许多字段的结构)传递给函数时节省内存。在传递之前复制此类数据类型将花费时间并消耗内存。这是程序员更喜欢大数据类型指针的另一个原因。
PS:请参考提供的详细解释和示例代码链接。
Pointers allow you to refer to the same space in memory from multiple locations. This means that you can update memory in one location and the change can be seen from another location in your program. You will also save space by being able to share components in your data structures. You should use pointers any place where you need to obtain and pass around the address to a specific spot in memory. You can also use pointers to navigate arrays: An array is a block of contiguous memory that has been allocated with a specific type. The name of the array contains the value of the starting spot of the array. When you add 1, that takes you to the second spot. This allows you to write loops that increment a pointer that slides down the array without having an explicit counter for use in accessing the array.
下面是一个C语言的例子:
char hello[] = "hello";
char *p = hello;
while (*p)
{
*p += 1; // increase the character by one
p += 1; // move to the next spot
}
printf(hello);
打印
ifmmp
因为它取每个字符的值并加1。
在很大程度上,指针是数组(在C/ c++中)——它们是内存中的地址,如果需要(在“正常”情况下),可以像数组一样访问它们。
因为它们是一个项目的地址,所以它们很小:它们只占用一个地址的空间。由于它们很小,将它们发送到函数是很便宜的。然后它们允许该函数在实际项目上工作,而不是一个副本。
如果您想进行动态存储分配(例如对于链表),则必须使用指针,因为它们是从堆中获取内存的唯一方法。
在c++中,如果你想使用子类型多态性,你必须使用指针。请参阅这篇文章:没有指针的c++多态性。
真的,仔细想想,这是有道理的。当您使用子类型多态性时,最终,您不知道将调用哪个类或子类的方法实现,因为您不知道实际的类是什么。
使用变量保存未知类的对象的想法与c++在堆栈上存储对象的默认(非指针)模式不兼容,在堆栈中分配的空间量直接对应于类。注意:如果一个类有5个而不是3个实例字段,则需要分配更多的空间。
请注意,如果您使用'&'通过引用传递参数,在幕后仍然涉及到间接(即指针)。'&'只是语法糖,它(1)省去了使用指针语法的麻烦,(2)允许编译器更严格(例如禁止空指针)。