【问题标题】:C language: why do these two printf statements print different thingsC语言:为什么这两个printf语句打印不同的东西
【发布时间】:2017-08-07 04:38:36
【问题描述】:
#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 语句会产生不同的结果。我怀疑这与我分配测试指针的方式有关,但我不知道如何修复它。

【问题讨论】:

    标签: c pointers struct printf return-value


    【解决方案1】:

    在您的情况下,node 是函数 init() 的局部变量,但您返回它的地址。所以,一旦函数返回,node 就不再存在了。

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

    但是,您可以返回结构变量本身,而不是指向它的指针,然后将调用者的返回值收集到另一个变量中,这样就可以了。

    【讨论】:

    • @weijazhou 请重新阅读答案中的最后一段,刚刚更新。 :)
    【解决方案2】:

    是的,由于返回指向函数本地对象的指针,您的代码具有未定义的行为。但似乎你的方法一开始就被误导了。您的 init 函数应该使用适当的初始值初始化结构,无需返回指针来执行此操作。您有三个选择:

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

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

      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 
      }
      
    3. 完全放弃该函数并提供一个代表节点初始值的宏:

      #define NODE_INIT_VAL { \
        .data = 5, .string = "hello", \
      }
      

      这使您可以简单地编写Node test = NODE_INIT_VAL;。这也是您希望使用静态存储持续时间初始化任何对象的方式。

    【讨论】:

      【解决方案3】:

      节点在函数init()中被定义为局部变量,所以它的内存在函数返回后被释放。

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

      node = malloc(sizeof(Node));
      

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

      【讨论】:

        【解决方案4】:

        更新 init() 以返回结构:

            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 回答说数据将不再有效。

        希望这是有用的。

        【讨论】:

          最近更新 更多