嵌入式开发学习日志(函数传递一维 / 二维数组、变量作用域 生命周期、内存分区) day11 持续更新中
一、函数和一维字符型数组字符串数组1. 传参语法//函数定义 返回值 函数名(char 数组名[]) { 函数体; } //函数调用 函数名(数组名);示例void print_str(char str[]) { } print_str(str);2. 核心注意点一维字符数组字符串传参不需要额外传递长度依靠字符串末尾\0判断结束数组作为函数参数传递本质传递数组首元素地址 在被调函数内sizeof(形参数组名)得到的是指针大小无法计算数组长度。练习字符串四大模拟函数mystrlen自定义函数统计字符串有效字符个数mystrcpyvoid mystrcpy(char dst[], char src[]);字符串拷贝mystrcatvoid mystrcat(char dst[], char src[]);字符串拼接mystrcmp自定义字符串比较返回 0、0、0二、函数和二维整型数组1. 传参语法//函数定义 返回值 函数名(int 数组名[][列数], int 行数) { } //调用 函数名(数组名, 行数);示例int a[3][4] {0}; void print_2D_array(int a[][4], int hang) { } print_2D_array(a, sizeof(a)/sizeof(a[0]));2. ⭐二维数组形参行数可以省略列数绝对不能省略正确int a[][4]错误int a[3][]在自定义函数内部无法通过 sizeof 计算总行数行数必须通过参数传入列数可以在函数内计算int lie sizeof(a[0]) / sizeof(a[0][0]);三、函数和二维字符型数组存放多个字符串1. 传参语法//定义 返回值 函数名(char 数组名[][列数], int 行数) {} //调用 函数名(数组名, 行数);示例char str[3][100] {0}; void print_2DC_array(char str[][100], int hang) { } print_2DC_array(str, 3);本质规则和二维整型数组一致必须指定每行字符串最大长度列数。易错提醒❌ 不能直接对二维字符数组整体使用strcpy ✅ 只能循环逐行调用strcpy每行str[i]才是合法字符串。四、变量的作用域空间角度哪里能访问作用域变量 / 标识符能够被访问、使用的代码范围。局部作用域{ }内部局部变量函数内定义变量、函数形参仅大括号内可用。全局作用域所有函数外部定义全局变量整个程序任意位置都可以访问。三条重要规则标识符遵循先定义后使用同一个作用域内不能定义同名变量 / 函数嵌套包含的作用域出现同名变量就近原则内层屏蔽外层同名变量。经典例题全局 i 与 main 局部 i 同名函数内访问全局 imain 内优先访问局部 i。五、变量的生命周期时间角度内存存活多久生命周期变量从分配内存到内存回收的时间段。1. 动态生命周期局部变量 auto进入局部范围开辟内存离开作用域内存立即回收存储在栈区。 未初始化局部变量随机垃圾值。2. 静态生命周期程序启动时分配内存整个程序运行结束才释放内存。 包含两类全局变量static修饰局部静态变量static 修饰局部变量特点作用域不变依旧只能在原本局部范围访问生命周期变长变为静态生命周期仅第一次调用初始化后续调用保留上次值。总结对照表变量类型作用域生命周期存储区域默认初始值普通局部变量 (auto)局部 {}动态出作用域释放栈区随机值全局变量整个程序静态程序结束释放数据区0static 局部变量局部 {}静态程序结束释放数据区0六、程序内存分区模型Linux gcc 环境程序运行时内存划分文本段 (.text)存放二进制代码指令只读数据区.data已经初始化的全局变量、static 静态变量.bss未初始化全局 /static 变量系统自动清零.rodata只读常量字符串常量堆区 (heap)手动申请释放malloc/free栈区 (stack)普通局部变量、函数形参函数调用自动分配回收内核区操作系统占用用户代码无法访问七、变量存储类型修饰符语法格式存储类型 数据类型 变量名;1. auto默认修饰符普通局部变量一般省略不写。2. static三大作用修饰局部变量延长生命周期保留上次数值修饰全局变量作用域限制在当前.c 文件其他文件无法 extern 访问修饰函数函数仅本文件内可用外部文件不能调用。3. register寄存器变量建议编译器将变量存放 CPU 寄存器加快访问速度只是建议编译器可以忽略限制寄存器变量不能取地址变量。4. extern用于声明外部标识符声明其他文件定义的全局变量声明其他.c 文件定义的函数extern 只做声明不会分配内存。