2017-03-16 51 views
2
#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语言:为什么这两个printf语句输出不同的东西

回答

3

在你的情况下,node是函数init()的局部变量,然而你返回这个地址。所以,一旦函数返回,就不再存在node

函数返回访问后返回值正在访问导致undefined behavior的无效内存。然而,你可以返回结构体变量本身,而不是指向它的指针,并且在调用者的另一个变量中收集返回值,它会生效。

+0

需要对代码进行哪些更改才能解决此问题? – Madnobleman

+0

@weijazhou请重新阅读答案中的最后一段,只是更新它。 :) –

0

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

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

node = malloc(sizeof(Node)); 

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

0

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

希望这是有用的。

1

是的,您的代码由于返回指向函数本地对象的指针而具有未定义的行为。但看起来你的做法是错误的开始。你的初始化函数应该用合适的初始值初始化一个结构体,不需要返回一个指针来完成它。你有三种选择:

  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;。这也是你希望如何初始化具有静态存储持续时间的任何对象。

相关问题