具体来说,当我要格式化所述整数的指针时。我正在研究《剥削的艺术》,它在以下代码片段中很突出。
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
int value = 5;
char buffer_one[8], buffer_two[8];
strcpy(buffer_one, "one"); /* Put "one" into buffer_one. */
strcpy(buffer_two, "two"); /* Put "two" into buffer_two. */
printf("[BEFORE] buffer_two is at %p and contains \'%s\'\n", buffer_two, buffer_two);
printf("[BEFORE] buffer_one is at %p and contains \'%s\'\n", buffer_one, buffer_one);
printf("[BEFORE] value is at %p and is %d (0x%08x)\n", &value, value, value);
printf("\n[STRCPY] copying %d bytes into buffer_two\n\n", strlen(argv[1]));
strcpy(buffer_two, argv[1]); /* Copy first argument into buffer_two. */
printf("[AFTER] buffer_two is at %p and contains \'%s\'\n", buffer_two, buffer_two);
printf("[AFTER] buffer_one is at %p and contains \'%s\'\n", buffer_one, buffer_one);
printf("[AFTER] value is at %p and is %d (0x%08x)\n", &value, value, value);
}
尽管buffer_one
是char[8]
类型,但是在某些情况下,例如作为函数参数传递时,它decays指向设置为数组第一个元素的指针。该指针将是char*
类型。
由于strcpy
的第一个参数应该是char*
类型,所以编译成功。
&
将产生指向该值的指针(对其进行引用)。在此上下文中,字符数组已被视为指针。
我敢于尝试比较buffer_one
和&buffer_one
的值。它们的类型不同,尽管编译器会警告您,但是实际值应该相同。
char buffer_one[8];
assert(buffer_one == &buffer_one); // should pass
请注意,这与可用作字符串变量的字符指针不同(从实用的角度来看)。引用指针会产生指向该指针的地址:
char *test = "lorem";
assert(test != &test); // should pass
为什么在字符数组不需要字符的情况下在printf中格式化指针时整数需要与号?
要打印诸如int
或char []
之类的对象的指针,代码使用&
获取该对象的地址。
int value = 5;
char buffer_one[8];
printf("Address of an int: %p\n", (void *) &value);
printf("Address of an array: %p\n", (void *) &buffer_one);
如果代码不使用&
,则对象必须是或转换为指针。下面,将数组buffer_one
转换为其第一个元素的地址。
printf("Address of an array element: %p\n", (void *) buffer_one);
结论由于&value
不会自动转换为指针,因此需要int
。 buffer_one
不需要&
,因为在这种用法下它会转换为指针。 buffer_one
也可以像任何对象一样使用&
。
数组buffer_one
的地址与其第一个元素的地址在同一存储位置。尽管它是非常常见,但是上面的最后2个打印将打印相同的指针,C不需要此。数组的地址和char
的地址为equivalent,尽管不必编码相同。