一、函数和一维字符型数组(字符串数组)
1. 传参语法
//函数定义 返回值 函数名(char 数组名[]) { 函数体; } //函数调用 函数名(数组名);示例:
void print_str(char str[]) { } print_str(str);2. 核心注意点
一维字符数组(字符串)传参不需要额外传递长度,依靠字符串末尾
'\0'判断结束;数组作为函数参数传递,本质传递数组首元素地址; 在被调函数内
sizeof(形参数组名)得到的是指针大小,无法计算数组长度。
练习(字符串四大模拟函数)
mystrlen:自定义函数,统计字符串有效字符个数mystrcpy:void mystrcpy(char dst[], char src[]);字符串拷贝mystrcat:void 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 同名,函数内访问全局 i,main 内优先访问局部 i。
五、变量的生命周期(时间角度:内存存活多久)
生命周期:变量从分配内存到内存回收的时间段。
1. 动态生命周期(局部变量 auto)
进入局部范围开辟内存,离开作用域,内存立即回收;存储在栈区。 未初始化局部变量:随机垃圾值。
2. 静态生命周期
程序启动时分配内存,整个程序运行结束才释放内存。 包含两类:
全局变量
static修饰局部静态变量
static 修饰局部变量特点
作用域不变:依旧只能在原本局部范围访问;
生命周期变长:变为静态生命周期;
仅第一次调用初始化,后续调用保留上次值。
总结对照表
变量类型 | 作用域 | 生命周期 | 存储区域 | 默认初始值 |
普通局部变量 (auto) | 局部 {} | 动态(出作用域释放) | 栈区 | 随机值 |
全局变量 | 整个程序 | 静态(程序结束释放) | 数据区 | 0 |
static 局部变量 | 局部 {} | 静态(程序结束释放) | 数据区 | 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 只做声明,不会分配内存。