这是我的演示代码:

#include <stdio.h>

#define WORK 0

typedef struct FooStruct {
    int x;
} FooStruct;

void setX(FooStruct *foo_ptr) {
    FooStruct foo = *foo_ptr;

    if (WORK) {
        foo_ptr->x = 10;
    } else {
        foo.x = 10;
    }
}

FooStruct makeFoo() {
    FooStruct foo = { 0 };

    setX(&foo);

    return foo;
}

int main(void) {
    FooStruct foo = makeFoo();

    printf("X = %d\n", foo.x);

    return 0;
}

如果WORK被定义为1,则代码按预期执行并打印“X=10”。
但是,如果WORK设置为0,它将打印“X=0”,或者如果FooStruct不是默认初始化的(即将FooStruct foo={};更改为FooStruct foo;),valgrind将在printf行上抛出一个值未初始化的错误。
我确信这是因为我的理解有差距,但对我来说,这两个不同的工作部门在运作上应该是完全相同的,所以我不确定误解是从哪里来的。
这是用gcc 8.2.0编译的,有/没有valgrind,结果相同。
=======================
编辑:
简化示例:
#include <stdio.h>

#define WORK 0

void setX(int *x_ptr) {
    if (WORK) {
        *x_ptr = 5;
    } else {
        int x = *x_ptr;
        x = 5;
    }
}

int main(void) {
    int x = 0;
    setX(&x);

    printf("X = %d\n", x);

    return 0;
}

最佳答案

当您#define WORK 0时,代码似乎也按预期工作如果在结构的副本中设置成员,则不应期望修改原始成员。
你有:

void setX(FooStruct *foo_ptr) {
    FooStruct foo = *foo_ptr;

    if (WORK) {
        foo_ptr->x = 10;    // Modify the structure pointed to by foo_ptr
    } else {
        foo.x = 10;         // Modify the local copy of the structure
    }
}

因为你做了一个MCVE(Minimal, Complete, Verifiable Example-谢谢!),对setX()中结构的修改副本没有任何操作。

10-06 12:02