c - 为什么 *curr 和 curr->val 的值相同?

标签 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();
}

当我打印出来时,*currcurr->val 是一样的。为什么?

我对 *curr 感到困惑。我认为 *curr&curr 指向的值。 (我是 C 语言的新手。)

最佳答案

首先,作为初学者,您应该尝试编写不引发警告的正确代码,然后再尝试理解幕后发生的事情以及为什么一些不正确的表达式仍然给出正确的结果。

C 是一种非常宽松的语言,只要编译器可以翻译它读取的内容,它通常会假定程序员知道他为什么编写它。这就是这里发生的事情。

在 C 中,struct 的地址可以转换为其第一个元素的地址。所以 (void *) &curr(void *) &(curr->val) 相同。在这里,我将所有内容都转换为 void * 以确保具有兼容的指针类型。

这意味着 *((int *) curr) 是一个完美定义的 C 表达式,它的值确实是 curr->val。但它是正确的,因为我写了一个明确的指针转换。

您编写的有效只是偶然,因为 curr 是聚合类型;您将 intitem * 传递给 printf 并仅使用它的第一个值 - 这不再标准C 和我只能假设一个经典 实现来猜测。但只需将您的打印命令替换为:

printf("%d - %d\n", curr->val, 12);
printf("%d - %d\n", *curr, 15);

你应该在第二个 printf 中看到垃圾,因为使用 %d 你声明你传递了一个简单的 int 而实际上传递了一个聚合.同样,每个标准都没有明确规定,但常见的实现应该会给出这个结果。

TL;DR: 由于 *curr 不是 intprintf("%d\n", *curr ); 是未定义的行为。这意味着任何事情都有可能发生,即使是预期的结果,但同一编译器或另一个编译器的不同版本,甚至编译参数的更改都可能产生不同的结果,代码中的微小更改也可能会产生不同的结果。

并且 C 允许自动将指针转换为 void * 并且您永远不应该转换 malloc 的返回值,因为它可以隐藏错误。请写:

curr = malloc(sizeof(item));

它不再与 C++ 兼容,但它是正确的 C。

关于c - 为什么 *curr 和 curr->val 的值相同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38090856/

相关文章:

C 中指向指针数组的 Char 指针

c - 如何让VS2017忽略特定编译器的关键字?

java - 如果 `jobject` 代表同一个 Java 实例,它是否总是具有相同的地址?

c - 从开关内部更新全局变量

c++ - 为什么可以通过构造函数将临时值分配给引用?

c - 定义可变大小的 CHAR 指针

c - this pointer to pointer in a struct 是什么意思?

c - 需要在 C 中实现通用列表,避免插入时重复

c++ - 链表的冒泡排序

java - 单链表冒泡排序