C语言:为什么这两个printf语句打印不同的东西

时间:2017-03-16 06:25:45

标签: c pointers struct printf return-value

#include <stdio.h>
typedef struct {
    int data;
    char * string;
}Node;

Node * init(){
    Node node;
    node.data = 5;
    node.string = "hello";
    Node * point = &node;
    return point;
}
int main() {
    Node * test = init();
    printf("%d\n", test->data);
    printf("%d", test->data);   
}

为什么最后两个printf语句会产生不同的结果。我怀疑是否与我分配测试指针的方式有关,但我不知道如何修复它。

4 个答案:

答案 0 :(得分:3)

在您的情况下,node是函数init()的本地变量,但是,您返回此地址。因此,一旦返回函数,就不再存在node

在函数返回访问后,返回值是访问导致undefined behavior的无效内存。

然而,您可以返回结构变量本身,而不是指向它的指针,并在另一个变量中收集调用者的返回值,它可以解决。

答案 1 :(得分:1)

是的,由于返回指向函数本地对象的指针,您的代码具有未定义的行为。但是看起来你的方法开始时是错误的。你的init函数应该初始化一个具有正确初始值的结构,不需要返回指针来执行此操作。您有三种选择:

  1. 按价值回报,就像建议的另一个答案一样。

  2. 传递函数结构的地址以进行初始化。这释放了返回值,因此您可以发出成功或失败的信号:

    $company_name = $_POST['company_name'];
    update_option( 'theme_options', $company_name );
    
  3. 完全放弃该函数并提供一个代表节点初始值的宏:

    bool init(Node *node) { // must include stdbool.h
        if(!node)
          return false;
    
        node->data = 5;
        node->string = "hello";
        return true;
    }
    
    //...
    
    Node test;
    if(!init(&test)) {
      //failed to initialize, handle the error 
    }
    

    这使您可以简单地编写#define NODE_INIT_VAL { \ .data = 5, .string = "hello", \ } 。您还希望如何初始化具有静态存储持续时间的任何对象。

答案 2 :(得分:0)

节点在函数init()中定义为局部变量,因此在函数返回后释放内存。

您应该将节点定义为全局变量(我不喜欢全局变量:-))或通过调用malloc来分配内存。

node = malloc(sizeof(Node));

如果您不再需要节点,请不要忘记释放内存。

答案 3 :(得分:0)

更新init()以返回struct:

    Node init(){
    Node node;
    node.data = 5;
    node.string = "hello";
    return node;
}
然后

访问它,如下所示:

Node testNode = init();
printf("%d\n", testNode.data);
printf("%d", testNode.data);

或者如果你想使用这样的指针:

Node testNode = init();
Node* pointerToNode = &testNode;
printf("%d\n", pointerToNode->data);
printf("%d", pointerToNode->data);

原因是@Sourav回答说数据不再有效。

希望这很有用。