C 将结构传递给函数并将其赋值
很抱歉,如果之前已经有人问过这个问题,但是我对传入和为结构赋值感到有点困惑C 将结构传递给函数并将其赋值,c,pointers,struct,C,Pointers,Struct,很抱歉,如果之前已经有人问过这个问题,但是我对传入和为结构赋值感到有点困惑 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(&firs
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()内mallock结构,就不应该将pointer*test in func()分配给第二个结构,因为它的作用域主要在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);
}
这段代码是完全有效的,尽管不是最优的
返回second
的地址是非法的,但事实并非如此。当您说*test=second
时,您是在将second
的值分配给解除引用的指针。编译器将生成代码来复制结构的每个元素
它不理想的原因是因为那份拷贝。相反,考虑一下:
void func(test_t * test)
{
test->x = 2;
test->y = 3;
}
这样,编译器将直接分配给指向结构的字段
这段代码是完全有效的,尽管不是最优的
返回second
的地址是非法的,但事实并非如此。当您说*test=second
时,您是在将second
的值分配给解除引用的指针。编译器将生成代码来复制结构的每个元素
它不理想的原因是因为那份拷贝。相反,考虑一下:
void func(test_t * test)
{
test->x = 2;
test->y = 3;
}
通过这种方式,编译器将直接分配给指向结构的字段。参数
test
是函数func
的本地参数,并且在函数外部不可见对其值的更改
但是,您没有更改test
的值。您正在解引用它所指向的内存位置并写入该位置。在这种情况下,test
包含main
中第一个变量的地址
因此,当您在func
中分配给*test
时,实际上是在main
中首先分配给。这就是为什么您可以在函数之外看到结果
因此,这段代码将按照您的预期工作,尽管它不是最优的。正如在另一个答案中提到的,将值分配给结构的本地实例,然后再将其分配给取消引用的指针,您只需取消引用指针并直接写入每个字段即可
void func(test_t * test)
{
test->x = 2;
test->y = 3;
}
参数test
是函数func
的本地参数,其值的更改在函数外部不可见
但是,您没有更改test
的值。您正在解引用它所指向的内存位置并写入该位置。在这种情况下,test
包含main
中第一个变量的地址
因此,当您在func
中分配给*test
时,实际上是在main
中首先分配给。这就是为什么您可以在函数之外看到结果
因此,这段代码将按照您的预期工作,尽管它不是最优的。正如在另一个答案中提到的,将值分配给结构的本地实例,然后再将其分配给取消引用的指针,您只需取消引用指针并直接写入每个字段即可
void func(test_t * test)
{
test->x = 2;
test->y = 3;
}
为什么要创建第二个second
,然后用它跺test
?为什么不直接操纵test
。它并不意味着有用;这是为了指出一些事情。我的问题仍然存在。在什么情况下,直接操纵它不是更好的选择?@tadman Like HTNW说,这是测试代码。在应用程序方面,我有一个函数,可以通过ioctl调用设置结构的值。我试着看看我原来的(基本上是我的测试代码)是否有效,或者我是否应该更改它。我认为你的ioctl调用示例比这个人为的例子提供了更多信息。这个虚拟结构包含两个int
值,所以笨拙地复制它不会有什么大不了的。另一些可能包含可能会出现问题的自引用指针。如果你能更好地说明你实际上在做什么,你可以确信你所做的是正确的。为什么要创建second
,然后用它跺脚test
?为什么不直接操纵test
。它并不意味着有用;这是为了指出一些事情。我的问题仍然存在。在什么情况下,直接操纵它不是更好的选择?@tadman Like HTNW说,这是测试代码。在应用程序方面,我有一个函数,可以通过ioctl调用设置结构的值。我试着看看我原来的(基本上是我的测试代码)是否有效,或者我是否应该更改它。我认为你的ioctl调用示例比这个人为的例子提供了更多信息。这个虚拟结构包含两个int
值,所以笨拙地复制它不会有什么大不了的。另一些可能包含可能会出现问题的自引用指针。如果你能更好地说明你实际上在做什么,你可以确信你所做的是正确的。谢谢你的快速回复!出于某种原因,我想得太多了,担心第二个会出现在堆栈上,一旦函数调用结束,值就会变成垃圾。感谢您的快速回复!出于某种原因,我想得太多了,担心第二个会出现在堆栈上,一旦函数调用结束,值就会变成垃圾。谢谢你的解释!我在考虑经典的“返回函数中声明的数组”以及这些值如何成为垃圾。那是