2017-10-10 68 views
0

对不起,如果这已经被问过,但我有点混淆传入和赋值给结构。将结构传递给一个函数并分配它

typedef struct test { 
    int x; 
    int y; 
} test_t; 

void func(test_t * test) 
{ 
    test_t second; 
    second.x = 2; 
    second.y = 3; 

    *test = second; 
} 

void main() 
{ 
    test_t first; 
    func(&first); 
} 

这是有效的吗?如果我没有记错的话,没有在func()内部结构化malloc,你不应该把func()中的指针* test指定给struct second,因为它的作用域主要在func()内部,并且一旦函数返回就会丢失。但是,在main()中打印出来的值是正确的。

有什么不同的方法来实现这个结果?这只是为了澄清一些混乱和健忘的记忆。

编辑:

的什么,我试图做的是这方面的一个更清楚的例子:

typedef struct args 
{ 
    int status; 
    int id; 
    unsigned long long start_address; 
    unsigned long long end_address; 
    unsigned long long size; 
} args_t; 

void ioctl_call(args_t *args) 
{ 
    args_t params; 

    /* get values */ 
    ioctl(fd, cmd, params); 

    *args = params; 
} 

void main() 
{ 
    args_t args; 
    iotcl_call(&args); 
    printf("%d\n", args.id); 
} 
+1

为什么创建'second',然后踩着'test'呢?为什么不直接操作'test'呢? – tadman

+0

@tadman这是示例代码。这并不意味着有用;它的意思是指出一些东西。 – HTNW

+0

我的问题依然存在。在什么情况下不会直接操纵它是更好的选择? – tadman

回答

4
void func(test_t * test) 
{ 
    test_t second; 
    second.x = 2; 
    second.y = 3; 

    *test = second; 
} 

此代码是完全有效的,尽管低于最佳。

返回地址second是违法的,但这不是发生了什么事。当您说*test = second时,您将second分配给解除引用的指针。编译器将生成代码以复制该结构的每个元素

它不理想的原因是因为该副本。相反,请考虑:

void func(test_t * test) 
{ 
    test->x = 2; 
    test->y = 3; 
} 

通过这种方式,编译器将直接指定指向结构的字段。

+0

感谢您的快速回复!出于某种原因,我过度思考,并担心第二个将会出现在堆栈中,一旦函数调用结束,这些值将变成垃圾。 – chewboy8

0

参数test位于函数func的本地,并且在函数外部更改其值不可见。

但是,您不会更改test的值。你是解除引用它指向的内存位置并写入该位置。在这种情况下,test包含main中变量first的地址。

所以,当你分配给*testfunc你实际上是在main分配给first。这就是为什么你可以看到功能以外的结果。

因此,此代码将按照您的预期工作,虽然它不是最优的。正如在另一个答案中提到的,相反,将值分配给结构的本地实例,然后将其分配给解除引用的指针,您可以直接解引用指针并直接写入每个字段。

void func(test_t * test) 
{ 
    test->x = 2; 
    test->y = 3; 
} 
+0

感谢您的解释!我正在考虑经典的“返回一个函数内部声明的数组”,以及这些值是如何变成垃圾的。这就是为什么我担心这个例子。 – chewboy8

相关问题