我们知道,在 C 中,函数参数传递只有两种方式,值传递、引用传递。
值传递的时候,会把对应的值复制一份传到函数中,形参和原变量是不同的两个变量,而引用传递只是把原变量的地址传递给形参,形参根据这个地址拿到对应的变量。
引用传递的时候,我们需要通过解引用 (*xxx)
的方式拿到变量,这个时候我们就拿到了原始变量,我们在函数中所有针对该变量的操作都是针对原始变量的操作,因为它们是同一个变量。
那这个规则对结构体变量来说是否还适用呢?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
   | #include <stdio.h>
  typedef struct User {     char *name;     int age; } User;
  void test1(User user) {     user.name = "name1";     printf("test1: user address = %p\n", (void*)&user);           printf("test1: name address = %p\n", (void*)&user.name);  }
  void test2(User *user) {     user->name = "name2";     printf("test2: user address = %p\n", (void*)&user);            printf("test2: name address = %p\n", (void*)&user->name);  }
  int main() {     User user = {.age = 23, .name = "name"};     printf("origin: user address = %p\n", (void*)&user);           printf("origin: name address = %p\n", (void*)&user.name); 
      test1(user);     printf("test1: user.name = %s\n", user.name);             
      test2(&user);     printf("test2: user.name = %s\n", user.name);             
      return 0; }
   | 
 
输出:
1 2 3 4 5 6 7 8
   | origin: user address = 0x7ffee7aae798 origin: name address = 0x7ffee7aae798 test1: user address = 0x7ffee7aae760 test1: name address = 0x7ffee7aae760 test1: user.name = name test2: user address = 0x7ffee7aae768 test2: name address = 0x7ffee7aae798  // 和原始 user 的地址一致 test2: user.name = name2
   | 
 
有人会发现
printf("test2: user address = %p\n", (void*)&user);
输出的地址并不是原始 user 的地址,这是为什么呢?
其实实际上 void test2(User *user)
test2(&user);
这两句还是值传递,只是传递的值是一个指针的地址。而上面的打印
&user 的地址实际上
是打印保存这个指针地址变量的地址,听起来有点拗口,但实际上就是这样,我们在
test2
内拿到了一个地址,我们会根据这个地址拿到原始的变量。
如何证实这一点呢?
在 test2 里面加上这一行,获取解引用后的
user 的地址,发现指向是原始 user 的地址。
1
   | printf("test2: user address = %p\n", (void*)&(*user)); // 0x7ffee7aae798
  | 
 
结论:值传递、引用传递的规则对于结构体变量传参同样适用。