c - 指针在 printf 后改变值

标签 c pointers gcc printf clang

所以今天我试图在 C 中实现简单的堆栈,但我遇到了以下问题,我无法解决或解释为什么会发生。

#include<stdio.h>

typedef struct stack_element stack_element;
typedef struct stack stack;

struct stack_element
{
    void* data;
    stack_element* next;
};

struct stack
{
    stack_element* top;
    int size;
    int max_size;
};

void push(stack* this, stack_element to_add)
{
    if(this->top == NULL)
    {
        this->top = &to_add;
        this->top->next = this->top;
        printf("%p\n", this->top);
        printf("%p\n", this->top->next);
        printf("First\n");
        return;
    }
}

void debug(stack* this)
{
    if(this->top == NULL) return;
    printf("Sample 1 %p\n", this->top);
    printf("Sample 2 %p\n\n", this->top->next);
}

int main()
{
    stack_element* tmp = malloc(sizeof(stack_element));
    stack* st = malloc(sizeof(stack)); 
    tmp->data = 1;
    push(st, *tmp);
    printf("Sample 1 %p\n", st->top);
    printf("Sample 2 %p\n\n", st->top->next);
    debug(st);
    printf("Sample 1 %p\n", st->top);
    printf("Sample 2 %p\n\n", st->top->next);
    printf("END\n");
    return 0;
}

上面的代码给出了一些奇怪的结果,如果我改变编译器,也会有不同的结果。

我试过的第一个编译器是 gcc,它给出了以下输出:

0x7ffd6d96d3b0
0x7ffd6d96d3b0
First
Sample 1 0x7ffd6d96d3b0
Sample 2 0x7ffd6d96d3b0

Sample 1 0x7ffd6d96d3b0
Sample 2 0x400670

Sample 1 0x7ffd6d96d3b0
Sample 2 0x40068d

END

第二个结果来自 clang:

0x7ffd6d05fb30
0x7ffd6d05fb30
First
Sample 1 0x7ffd6d05fb30
Sample 2 0x7ffd6d05fb30

Sample 1 0x7ffd6d05fb30
Sample 2 0x2042030

Sample 1 0x7ffd6d05fb30
Sample 2 0x2042030

END

我的第一个问题是,为什么当我从 void debug 打印它时,示例 2 甚至发生了变化?我还尝试注释掉调试函数调用,但结果也很奇怪。在 gcc 中,所有样本都符合预期,但在 clang 中,样本 2 存在差异,原因不明。

我的第二个问题是为什么在编译这段代码时编译器之间甚至存在差异?

希望我已经发布了有关我遇到的问题的足够信息,如果没有,请在评论中写信给我以发布更多信息。

最佳答案

您的 push 函数按值获取第二个参数,因此它创建了 struct stack_element 的本地副本。这意味着行 this->top = &to_add; 将指针 top 重定向到指向局部变量(具有自动存储持续时间)。在函数 push 结束后,变量的生命周期结束,将 top 更改为悬挂指针。因此,取消引用 this->top->next(和 st->top->next)调用未定义的行为

您最有可能打算做的是将 push 的第二个参数作为指针:void push(stack* this, stack_element* to_add) 并更改行:

this->top = &to_add;

this->top = to_add;

注意:您建议在 push 中使用 malloc 是另一种可能性,但是这可能会产生不清晰的代码,因为它需要调用者知道 top 需要 freed 以避免内存泄漏。或者,您也可以提供一个“析构函数”函数,它负责所有内存管理,对调用者隐藏它。

关于c - 指针在 printf 后改变值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42735993/

相关文章:

c++ - 使用 shared_ptr 列表撤消/重做

c - 初始化结构数组(编译器错误 : initializer element is not constant)

c - 出现 Apple Mach-O 链接器错误 C99。我如何解决它?

使用头文件编译

c - 使用指针重写 C 代码

C++指针练习

c++ - 调用 __do_global_dtors_aux 时双重释放或损坏 (!prev)

c++ - 在 Makefile 中指定库路径

c - E Balaguruswamy 书第 1 章主题子例程第 3 版中的 C 代码错误

android - Android 上的 GStreamer