链表实现中同地址指针解引用输出不同值的技术疑问
嘿,这个问题的根源其实很明确——你误用了printf的格式说明符,触发了C语言里的未定义行为,才出现了这种看似矛盾的输出。
先帮你理清楚当前的状况:
- 你已经确认
walker和head存储的是同一个地址(输出里value in walker和value in head都是0x7fff5ae88af0),这说明两个指针本身是完全没问题的; - 用
head->value和walker->value能得到正确的1,也印证了它们指向的结构体是正常的。
那为什么用%d打印*walker和*head会出现不一样的结果?
核心原因:格式符与参数类型不匹配
*walker和*head的类型是struct Node,但%d格式符要求传入的是int类型的值。当你把一个结构体传给期望int的printf参数时,编译器会按照结构体的内存布局把它的字节内容强制当成int来解析——这属于典型的未定义行为,结果完全不可预测。
看你的结构体定义:
struct Node { int value; struct Node* next; };
在大多数系统中,这个结构体的内存布局是先放int value,接着放指针next。当你用%d打印*head时,刚好读取了结构体的前4字节(假设int是4字节),也就是value的值,所以看起来输出了正确的1——这纯粹是巧合!而打印*walker时,可能因为栈内存布局、参数传递顺序的差异,导致printf读取到的是结构体里next指针的部分字节,或者其他随机内存内容,所以输出了像1525189360这样的奇怪数字。
正确的处理方式
如果你想打印结构体里的数值,绝对不能直接用%d打印整个结构体,必须明确访问它的成员:
- 打印
value成员:用printf("%d", walker->value)或者等价的printf("%d", (*walker).value) - 如果想查看整个结构体的信息,可以逐个打印成员,比如:
printf("walker points to struct: value=%d, next=%p\n", walker->value, walker->next);
修正你的代码
看你写的printf语句:
printf("address of walker: %p, address of head: %p, value in walker: %p ,value in head: %p, value pointed to by walker: %d, value pointed to by head: %d\n", &walker, &head, walker, head, *walker, *head);
这里的最后两个参数*walker和*head都是struct Node类型,和%d完全不匹配。把它们换成walker->value和head->value,输出就会完全一致了。
最后再提醒一句:在C语言里,printf的格式说明符和参数类型必须严格对应,否则未定义行为会给你带来各种匪夷所思的bug,一定要注意!
内容的提问来源于stack exchange,提问作者jeremy radcliff

