function's argument is function's local variable, build in stack memory, released when function exit. its value copyed from out variables.

简介:
C的函数, 如果它有参数. 参数是怎么传递的.
有这么几点必须明白:
1. 参数传递时, 函数体内部将在内存stack区域新建作用在这个函数内部的本地变量.
如 void test1 (char * a) , 这里 a 是函数的本地变量. 
2. 传递的是值, 而不是变量.
如 test1(b), 函数体里面的 a 是拷贝了b这个变量的值, 而不是b这个变量.

来做个测试就会明白 : 
[root@digoal zzz]# cat a.c
#include <stdio.h>
#include <string.h>

int main() {
typedef struct fish {
  int age;
  char name[10];
} fish;

char * gt1 = "abcdefg";
char gt2[10] = "abcdefg";
int gt3 = 100;
fish gt4 = {20, "linux"};

void test1 (char * t1) {
  fprintf(stdout, "&t1:%p, t1:%p, >1:%p, gt1:%p\n", &t1, t1, >1, gt1);
}

void test2 (char t2[]) {
  fprintf(stdout, "&t2:%p, t2:%p, >2:%p, gt2:%p\n", &t2, t2, >2, gt2);
}

void test3 (int t3) {
  fprintf(stdout, "&t3:%p, >3:%p\n", &t3, >3);
}

void test4 (struct fish t4) {
  fprintf(stdout, "&t4:%p, >4:%p\n", &t4, >4);
}

  test1(gt1);
  test2(gt2);
  test3(gt3);
  test4(gt4);
  return 0;
}
结果 : 
[root@digoal zzz]# gcc -O3 -Wall -Wextra -Werror -g ./a.c -o a && ./a
&t1:0x7fff08f00b10, t1:0x400748, >1:0x7fff08f00ad0, gt1:0x400748  // 字符串在这里是常量放在constants内存区域, 所以地址比较小. 而变量放在stack区域, 所以地址比较大 . 
&t2:0x7fff08f00b10, t2:0x7fff08f00aec, >2:0x7fff08f00aec, gt2:0x7fff08f00aec   // 这里要特别注意, 函数体内存储的是个指针变量, 不是数组, 这个指针指向了外部的数组 . 
&t3:0x7fff08f00b1c, >3:0x7fff08f00ae8
&t4:0x7fff08f00b00, >4:0x7fff08f00ad8
// 这里我分别测试了指针变量,数组,int型以及结构体 . 
AI 代码解读

结果表明 : 
1. 指针变量作为参数类型时, 传递的是指针存储的地址值. 而指针变量的地址是不一样的, 因为在函数体内的t1的地址与gt1地址不一致.
2. 数组作为参数类型时(这里要注意, 数组作为参数变量, 这个变量在函数体内部是指针, 也就是失去了数组的特性), 
    传递的是外部数组gt2的地址, 所以地址 (t2 = &gt2 = gt2),  (因为数组变量名在编译时替换成地址). 参数变量的地址与参数变量存储的地址不一致. 也说明了参数变量虽然是数组. 但是显然它在函数体内其实是指针. 如果是数组的话, &t2 应该等于 t2.
3. int作为参数类型时, 传递的是值. 可以看到&t3 不等于 &gt3
4. 结构体作为参数类型时, 传递的也是值.  可以看到&t4 不等于 &gt4 . 
5. &t1 = &t2 又是为什么呢, 前面说了 函数体内部的变量都放在stack里面, 当函数调用结束就会释放掉, 所以test1 执行完再执行test2 是有可能申请到同一片stack里面的地址的.

另外要说的是 , 由于是拷贝, 所以我们要特别注意变量存储的是什么东西. 如参数类型是指针, 拷贝过去就是这个指针存储的地址. 所以他们会指向同一个地方。
所以如果结构体中如果有使用数组存储的, 或者指针存储的元素, 他们拷贝的内容是大不一样的.
例如 : 
[root@digoal zzz]# cat a.c
#include <stdio.h>
#include <string.h>

int main() {

typedef struct fish {
  int age;
  char name[10];
  char * nick;
} fish;

fish gt4 = {20, "linux", "world"};

void test4 (struct fish t4) {
  fprintf(stdout, "&(t4.name):%p, &(gt4.name):%p, t4.name:%p, gt4.name:%p\n", &(t4.name), &(gt4.name), t4.name, gt4.name);
  fprintf(stdout, "&(t4.nick):%p, &(gt4.nick):%p, t4.nick:%p, gt4.nick:%p\n", &(t4.nick), &(gt4.nick), t4.nick, gt4.nick);
}

  test4(gt4);
  return 0;
}
结果
[root@digoal zzz]# gcc -O3 -Wall -Wextra -Werror -g ./a.c -o a && ./a
&(t4.name):0x7fffed837484, &(gt4.name):0x7fffed8374a4, t4.name:0x7fffed837484, gt4.name:0x7fffed8374a4
&(t4.nick):0x7fffed837490, &(gt4.nick):0x7fffed8374b0, t4.nick:0x4006e8, gt4.nick:0x4006e8
AI 代码解读

来解释一下 : 
1.  &(t4.name):0x7fffed837484, &(gt4.name):0x7fffed8374a4 这两个指存放name这个元素的地址. 它们不相等, 是因为函数函数传参是新建本地变量与值拷贝的过程. 所以t4和gt4是放在两块内存区域的, 因此t4和gt4的name它们的存放地当然不一样.
2. t4.name:0x7fffed837484, gt4.name:0x7fffed8374a4 这两个不一样, 因为t4在函数内部是一个全新的结构体变量, 所以t4.name 存储的是数组本身, 而没有退化成指针, 所以拷贝的是数组的内容. 因此可以看出&(t4.name) = t4.name ; &(gt4.name) = gt4.name. 因为数组即地址(多次提到).
3. &(t4.nick):0x7fffed837490, &(gt4.nick):0x7fffed8374b0 这两个不相等 . 和第一条的解释一样.
4. t4.nick:0x4006e8, gt4.nick:0x4006e8 这两个指的是nick这个指针存放的内容转成地址打印出来, 当然是相同的.

最后, 脑子里有一副内存的图就比较好理解了.
目录
打赏
0
0
0
0
20696
分享
相关文章
成功解决TypeError: ‘encoding’ is an invalid keyword argument for this function
成功解决TypeError: ‘encoding’ is an invalid keyword argument for this function
|
6月前
|
Python Tricks : Function Argument Unpacking
Python Tricks : Function Argument Unpacking
56 1
|
8月前
解决微软云Azure Function运行报错-Value cannot be null. (Parameter ‘provider‘)
解决微软云Azure Function运行报错-Value cannot be null. (Parameter ‘provider‘)
185 4
|
8月前
|
【Azure 应用服务】Azure Function Python函数部署到Azure后遇见 Value cannot be null. (Parameter 'receiverConnectionString') 错误
【Azure 应用服务】Azure Function Python函数部署到Azure后遇见 Value cannot be null. (Parameter 'receiverConnectionString') 错误
|
8月前
|
【Azure 应用服务】Azure Function (PowerShell) 执行时报错 "out of memory"
【Azure 应用服务】Azure Function (PowerShell) 执行时报错 "out of memory"
【Azure Function】调试 VS Code Javascript Function本地不能运行,报错 Value cannot be null. (Parameter 'provider')问题
【Azure Function】调试 VS Code Javascript Function本地不能运行,报错 Value cannot be null. (Parameter 'provider')问题
函数计算操作报错合集之 显示"Function timed out after 30 seconds (maxMemoryUsage: 73.38MB)" ,该如何解决
在使用函数计算服务(如阿里云函数计算)时,用户可能会遇到多种错误场景。以下是一些常见的操作报错及其可能的原因和解决方法,包括但不限于:1. 函数部署失败、2. 函数执行超时、3. 资源不足错误、4. 权限与访问错误、5. 依赖问题、6. 网络配置错误、7. 触发器配置错误、8. 日志与监控问题。
191 2
漏刻有时环境部署:php安装提示Can‘t use function return value in write context
漏刻有时环境部署:php安装提示Can‘t use function return value in write context
119 0
漏刻有时数据可视化大屏常见问题(1): Can’t use function return value in write context
漏刻有时数据可视化大屏常见问题(1): Can’t use function return value in write context
136 0
cv2.error: OpenCV(4.5.2) : -1 : error: (-5:Bad argument) in function ‘rectangle‘
cv2.error: OpenCV(4.5.2) : -1 : error: (-5:Bad argument) in function ‘rectangle‘
561 0

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等