繁体   English   中英

printf() 在 C 中打印参数和指针

[英]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]);

第一个参数很好,将始终打印您期望的内容。 第二个参数调用前面提到的未定义行为。 在使用特定编译器的特定机器上,它会像前面的示例一样打印第二个%xmemory内容。 在第三个%x的情况下,它在堆栈中查找接下来的 4 个字节。 这不是您传入的y[0]而是传入*ynext的内容,因为为包含 8 个字节的第二个参数传递了一个struct mine

但同样,这种行为是未定义的。 如果您使用不同的编译器、更改编译器设置或在不同的机器上运行,它可能会打印出完全不同的内容。 无法保证发生在您身上的事情会永远发生。

正如您在评论中建议的那样,这不是printf的问题。 这是您调用未定义的行为。

编辑:

如果你试图查看的地址y->memory*yy[0]你需要通过每一项的地址,并使用%p格式说明正确输出它们:

printf("%p %p %p\n", (void *)&y->memory, (void *)y, (void *)&y[0]);

由于y[0]等价于*(y + 0) (即*y ),并且由于memory是结构的第一个字段,因此这将输出三个相同(依赖于系统)的值。

这是我打印指针的方式的问题吗

代码从不尝试打印指针。 代码尝试打印*yy[0]y->memory 这些是minemineunsigned类型。

要打印y类的指针,请使用 printf 说明符"%p"并转换为(void *)如果指针未准备好void *

printf("%p\n", (void *) y);

要打印struct minestruct 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM