[英]Printf() printing of arguments and pointers in C
好的,所以基本上我试图通过 printf 和各种形式的指针来理解这里发生了什么
这是代码
#include <stdio.h>
#include <stdlib.h>
typedef struct mine{
unsigned int memory;
struct mine * next;
}mine;
int main(int argc, char *argv[]){
mine * y;
y = (struct mine *)malloc(sizeof(struct mine));
y->memory = 0xBEEFDEAD;
printf("%x\n",*y);
printf("%x\n",y[0]);
printf("%x\n",y->memory);
printf("%x %x %x\n",y->memory, *y,y[0]);
return 0;
}
这是输出
beefdead
beefdead
beefdead
beefdead beefdead 7c00c0
正如您所看到的,当它们单独分开和组合在一起时,打印的相同指针会使用 printf 给出不同的结果
这是我打印指针的方式的问题,还是 printf 的问题
也可以 *y = y[0] = y->memory
从输出中我不确定这个问题的答案
当你这样做时:
printf("%x\n",*y);
或这个:
printf("%x\n",y[0]);
您正在为%x
格式说明符提供一个struct mine
。 这是未定义的行为,这意味着任何事情都可能发生。
在特定机器上的特定编译器的情况下, %x
说明符可能会获取传入的struct mine
的前 4 个字节,这恰好是memory
的内容。 但是你不能依赖这种行为。 如果您使用不同的编译器,甚至在不同的机器上运行相同的可执行文件,它很可能会做一些不同的事情。
在这一行的情况下:
printf("%x %x %x\n",y->memory, *y,y[0]);
第一个参数很好,将始终打印您期望的内容。 第二个参数调用前面提到的未定义行为。 在使用特定编译器的特定机器上,它会像前面的示例一样打印第二个%x
的memory
内容。 在第三个%x
的情况下,它在堆栈中查找接下来的 4 个字节。 这不是您传入的y[0]
而是传入*y
时next
的内容,因为为包含 8 个字节的第二个参数传递了一个struct mine
。
但同样,这种行为是未定义的。 如果您使用不同的编译器、更改编译器设置或在不同的机器上运行,它可能会打印出完全不同的内容。 无法保证发生在您身上的事情会永远发生。
正如您在评论中建议的那样,这不是printf
的问题。 这是您调用未定义的行为。
编辑:
如果你试图查看的地址y->memory
, *y
和y[0]
你需要通过每一项的地址,并使用%p
格式说明正确输出它们:
printf("%p %p %p\n", (void *)&y->memory, (void *)y, (void *)&y[0]);
由于y[0]
等价于*(y + 0)
(即*y
),并且由于memory
是结构的第一个字段,因此这将输出三个相同(依赖于系统)的值。
这是我打印指针的方式的问题吗
代码从不尝试打印指针。 代码尝试打印*y
、 y[0]
、 y->memory
。 这些是mine
、 mine
和unsigned
类型。
要打印y
类的指针,请使用 printf 说明符"%p"
并转换为(void *)
如果指针未准备好void *
。
printf("%p\n", (void *) y);
要打印struct mine
等struct mine
的内容,请打印各个子字段。 见下文。
与传递的扩充不匹配的打印格式说明符会导致 C 规范指定的行为为未定义行为。 结果可能是什么? 对这种行为的任何解释都依赖于许多关于底层生成代码的假设,坦率地说,这是大量的猜测工作。
将匹配的printf()
格式说明符与匹配类型的值一起使用。
许多编译器警告这种不匹配。 确保完全启用编译器的警告。 节省您的时间。
"%x"
匹配一个unsigned
,而不是类型mine
。 结果:未定义的行为。
mine * y;
...
// printf("%x\n", *y);
// Instead:
printf("%x %p\n", y->memory, (void *) y->next);
printf("%x\\n", y[0]);
结果:未定义的行为。
// printf("%x\n", y[0]);
// Instead:
printf("%x %p\n", y[0].memory, (void *) y[0].next);
printf("%x\\n", y[0]);
结果:未定义的行为。
// printf("%x %x %x\n", y->memory, *y, y[0]);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.