van*_*ake 5 c pointers linked-list
考虑:
#include<stdlib.h>
#include<stdio.h>
struct node {
int val;
struct node *next;
};
typedef struct node item;
void main() {
item * curr, *head;
int i;
head = NULL;
for (i = 1; i <= 10; i++) {
curr = (item *)malloc(sizeof(item));
curr->val = i;
curr->next = head;
head = curr;
}
curr = head;
while (curr) {
printf("%d\n", curr->val);
printf("%d\n", *curr);
curr = curr->next;
}
getchar();
}
Run Code Online (Sandbox Code Playgroud)
当我打印出来,*curr并且curr->val是相同的.为什么?
我很困惑*curr.我认为*curr是值得&curr指出的.(我是C的新手)
首先作为一个初学者,你应该尝试编写正确的代码,在尝试理解引擎盖下发生的事情以及为什么一些不正确的表达式仍能给出正确的结果之前不会发出警告.
C是一种非常宽松的语言,只要编译器可以翻译它所读取的内容,通常假定程序员知道他为什么写它.这就是这里发生的事情.
在C中,a的地址struct可以转换为其第一个元素的地址.所以(void *) &curr是一样的(void *) &(curr->val).在这里,我将所有内容都转换void *为确保具有兼容的指针类型.
这意味着它*((int *) curr)是一个完美定义的C表达式,其值确实如此curr->val.但这是正确的,因为我写了一个显式指针.
你所写的作品只是偶然,因为curr是一个聚合型; 你传递一个int和item *到printf只使用它的第一个值-这不再是标准的C,我只能假设一个经典的实现来猜测.但只需用以下内容替换打印命令:
printf("%d - %d\n", curr->val, 12);
printf("%d - %d\n", *curr, 15);
Run Code Online (Sandbox Code Playgroud)
你应该在第二个看到垃圾printf,因为%d你声明你传递一个简单的int并实际传递一个聚合.在这里,每个标准都没有明确强制要求,但是通常的实现应该给出这个结果.
TL; DR:由于*curr不是int,printf("%d\n", *curr);是未定义的行为.这意味着任何事情都可能发生,甚至是预期的结果,但是相同编译器或其他编译器的不同版本,甚至编译参数的更改都可能产生不同的结果,代码中的微小变化也是如此.
并且C允许自动指针转换为和从void *而且你永远不应该转换返回值,malloc因为它可以隐藏错误.请写出:
curr = malloc(sizeof(item));
Run Code Online (Sandbox Code Playgroud)
它不再是C++兼容的,但它是否正确C.
dim*_*im8 -2
这里
\n\ncurr->val = i; \ncurr->next = head;\nhead = curr;\nRun Code Online (Sandbox Code Playgroud)\n\n首先你设置(*curr).val为i. 然后你curr->next指出head. 此时依旧NULL。然后你head指出curr. 这里有趣的部分是curr指向它的开头并*curr取消引用它,这本质上是curr->val,因为从那里开始 struct curr。
根据标准和这个答案
\n\n\n\n\n(C1x \xc2\xa76.7.2.1.13:“指向结构对象的指针,经过适当转换,指向其初始成员......反之亦然。作为结构对象内可能有未命名的填充,但不是在其开头。 ”)
\n
HEAD这意味着实际结构开始与其第一个元素的开始之间没有任何空格(填充)(或者也例如一些信息)。
编辑:
\n我没有谈论 UB,不是因为我没有看到它。OP 还要求别的东西。应该指出,但不是答案!这就是我们有评论部分的原因!
| 归档时间: |
|
| 查看次数: |
243 次 |
| 最近记录: |