一、二维字符数组
二维字符数组本质上就是一个字符串数组——每一行存一个字符串。
1. 定义
c
char str[5][32]; // 5行,每行最多31个字符(留1个给\0)
2. 元素的访问
c
str[0] // 访问第0行,代表第0个字符串 str[0][2] // 访问第0行第2列,单个字符
3. 初始化
c
// 方式一:逐字符初始化 char str[5][32] = { {'h', 'e', 'l', 'l', 'o', '\0'}, {'w', 'o', 'r', 'l', 'd', '\0'} }; // 方式二:字符串初始化(最常用) char str[5][32] = {"hello", "world", "how", "are", "you"}; // 方式三:全部置零 char str[5][32] = {0};4. 输入与输出
c
char str[5][32] = {0}; // 输入5个字符串 for (int i = 0; i < 5; i++) { scanf("%s", str[i]); // str[i] 本身就是地址,不用加& } // 输出5个字符串 for (int i = 0; i < 5; i++) { printf("str[%d] = %s\n", i, str[i]); }⚠️ 二维字符数组的每一行都是一个一维字符数组,
str[i]本身就是字符串的首地址,所以scanf不用加&。
二、函数
1. 为什么需要函数?
有些操作要反复做——比如求两个数的最大值、判断闰年。每次都把同样的代码复制粘贴一遍,代码会变得又臭又长,改一个地方要改好几处。
函数就是把重复的代码封装起来,哪里需要就调用哪里。
2. 函数的定义
c
函数类型 函数名(数据类型 形参1, 数据类型 形参2, ...) { 函数体; return 返回值; }几个要点:
函数名:规则和变量名一样,见名知意
形参:函数要处理的数据通过形参传进来
函数类型:返回值的数据类型,不写默认
int,没有返回值就写void返回值:函数运行完的结果,通过
return返回
c
// 例子:求两个整数中较大的那个 int max(int a, int b) { return (a > b) ? a : b; }3. 函数的调用
c
int result = max(10, 20); // result = 20
传参规则:
实参个数和形参个数必须一一对应
类型不匹配时会自动转换(按形参类型转)
4. 函数的声明
如果被调函数写在主调函数下面,需要先声明:
c
// 声明(告诉编译器有这个函数) int max(int a, int b); int main(void) { int m = max(10, 20); return 0; } // 定义 int max(int a, int b) { return (a > b) ? a : b; }如果被调函数写在主调函数上面,就不需要声明了。
三、变量的作用域和生存周期
1. 作用域(哪里能用)
局部变量:在函数或代码块(
{})内定义,只能在这个范围内使用全局变量:在所有函数外面定义,整个文件都能用
c
int global = 100; // 全局变量 void func(void) { int local = 10; // 局部变量 printf("%d\n", global); // ✅ 能用全局 } int main(void) { printf("%d\n", local); // ❌ 错误!main里看不到local printf("%d\n", global); // ✅ 能用全局 return 0; }2. 生存周期(什么时候存在)
局部变量:执行到定义时开辟空间,出了作用域就回收
全局变量:程序启动时就存在,程序结束才回收
四、变量的存储类型
1. auto(自动型,默认)
c
auto int a; // 等价于 int a;
存在栈区
不初始化就是随机值
进入作用域时开辟,退出时回收
2. register(寄存器存储)
c
register int a;
尽量放在CPU寄存器里(更快)
如果寄存器满了,等价于
auto
3. extern(外部声明)
声明变量或函数是在别处定义的,多文件编程时用。
4. static(静态存储)
作用域受限:只能在当前文件里用,防止多文件命名冲突
生命周期延长:程序启动时分配,程序结束才回收
默认初始化为0
c
static int count; // 默认值为0 static void helper(void) { } // 只能在当前文件用五、函数传参方式
值传递(C语言默认方式)
c
void swap(int a, int b) { int tmp = a; a = b; b = tmp; } int main(void) { int x = 10, y = 20; swap(x, y); printf("x=%d, y=%d\n", x, y); // 还是 10, 20,没变! return 0; }值传递的本质是"拷贝"——实参把自己的值复制一份给形参,形参怎么改都不影响实参。
六、今日总结
今天学了二维字符数组和函数,核心要点如下:
二维字符数组:
本质是字符串数组,每一行存一个字符串
定义:
char 数组名[行数][列数]初始化:
char str[3][32] = {"hello", "world", "C"};访问:
str[i]代表第i个字符串,str[i][j]代表第i个字符串的第j个字符输入输出:
scanf("%s", str[i])不用加&
函数部分:
函数三要素:定义(写逻辑)、调用(用逻辑)、声明(告诉编译器)
作用域:局部变量只在当前
{}内有效,全局变量整个文件都能用生存周期:局部变量随函数调用而生、随函数结束而灭,全局变量随程序
static关键字:让变量生命周期延长到程序结束,同时限制作用域在当前文件
值传递:C语言传参是"拷贝",形参改变不影响实参
今日感悟:
以前所有逻辑都堆在main函数里,写着写着很容易看混。把功能拆成一个个小函数之后,main函数变成了"目录",一眼就能看懂整个程序的流程,简洁易懂。