【发布时间】:2012-02-13 04:03:52
【问题描述】:
当谈到指针时,我有点困惑。
一些示例代码:
char str1[80];
char *p1;
cout <<"Enter a string"<<endl;
cin >> str1;
p1 = str1;
在最后一行代码中,如果 str1 包含“Test”,为什么 p1 现在包含“Test”。 p1 不还是一个指针吗?我认为指针只包含指向其他变量的地址。
【问题讨论】:
当谈到指针时,我有点困惑。
一些示例代码:
char str1[80];
char *p1;
cout <<"Enter a string"<<endl;
cin >> str1;
p1 = str1;
在最后一行代码中,如果 str1 包含“Test”,为什么 p1 现在包含“Test”。 p1 不还是一个指针吗?我认为指针只包含指向其他变量的地址。
【问题讨论】:
p1 不包含Test。它包含内存中一个字节的地址,该地址设置为字符T 的ASCII 值,后跟e、s、t 和一个0。该地址是数组@ 的地址987654327@,一个 80 个char 数组。
如果您尝试打印str1 或p1,您将获得输出Test。这是因为您无法将数组传递给函数,因此如果您尝试这样做,数组名称将衰减为指向第一个元素的指针,就像p1。所以str1 将衰减为指向T 的指针,而p1 已经是指向T 的指针,因此在打印时得到相同的输出,因为它们都指向内存中的相同地址。
【讨论】:
p1 是一个指针。
也就是说p1包含了str1的第一个字符的内存地址。
当您查看p1“持有”什么时,您可能做了类似cout << p1 或cout << p1[3] 的操作。其中任何一个都将取消引用 p1,将其视为指向字符数组的指针。
要查看p1 的实际值,请尝试cout << (void*)p1。这将与 str1 的实际值相同 - 如果您输入“测试”,则该内存位置包含“T”。
【讨论】:
指针保存地址,仅此而已。有时您取消引用指针以获取数据,有时您将指针传递给将取消引用它的代码。
例如:
p1 = 0; //Point to invalid memory address, but an address nonetheless
p1 = str1 //Point to a valid buffer. p1 now holds an new address, nothing else
if(*p1 == 'A') //Dereference the pointer (gives a character)
printf("The first character in str1 is A.\n");
您可以通过像这样重新组织您的程序来强调 p1 不保存指针以外的数据这一事实:
char str1[80];
char *p1;
p1 = str1; //Point to un-initialized memory, your compiler might complain.
//but p1 is happy. It holds an address, it will never "hold" anything else.
//*p1 is valid (will not crash) but holds random garbage, do not use it!
cout <<"Enter a string"<<endl;
cin >> str1; //Now str1 was initialized
if(*p1 == 'A') //Dereference the pointer (it is now a character)
printf("The first character in str1 is A.\n");
现在要强调 p1 和 str1 是同一个东西(内存中的相同地址)这一事实,将其添加到程序中:
str1[0] = 'A'; //Put a capital A in str1
if(*p1 == 'A') //Dereference the pointer (it is now a character)
printf("Now that we forced an A, this test is always true.\n");
【讨论】:
什么告诉你 p1 不是指针?
cout::<< 和 printf 等函数和运算符旨在打印字符串(以及其他数据类型),因此它们会为您适当地取消引用指针参数:给它一个指向字符串的指针,它会打印字符串在那个地址。如果你真的想让它把指针的值打印为地址,你必须用(void *) 强制转换它。
【讨论】:
请记住,对于数组:
int array[N];
array 的用法本质上表示&array[0],因此,以下内容相同:
PrintAddress(&array[0]); // void PrintAddress(int*);
PrintAddress(array);
这样,当你这样做时:
int *pAddress;
pAddress = &array[0];
PrintAddress(pAddress);
您可以将第二行修改为:
pAddress = array;
并且,为了完整起见,以下内容相同:
PrintAddress(&array[2]);
PrintAddress(array+2);
还有以下内容:
pAddress = array+5;
pAddress = &array[5];
【讨论】:
printf("Address: %p\n", (void *)p1);
将打印地址(来自how to see address of a structure in printf)。
printf("String: %s\n", p1);
将打印字符串。
第一个是p1的实际内容,第二个是这个内容在你的程序上下文中的含义意味着:p1是一个指向char的指针,这是通常的C 中表示字符串的方式(以 0 - '\0' 结尾)。
【讨论】: