今日学习内容
1. 二维数组作为函数参数
(1) 参数传递规则
- 整型二维数组:必须显式传递行数和列数
// 函数声明
void process_matrix(int mat[][4], int rows); // 列数必须显式指定
// 调用示例
int arr[3][4] = {0};
process_matrix(arr, 3);
- 字符型二维数组:
void print_strings(char str[][20], int count); // 每行最多19字符+'\0'
(2) 内存视角
- 数组名传递:实际传递的是首行地址(等价于
&arr[0][0]
) - 行数计算:必须在主调函数中计算后传递
int rows = sizeof(arr)/sizeof(arr[0]);
int cols = sizeof(arr[0])/sizeof(arr[0][0]);
2. 标识符作用域与可见性
(1) 作用域分类
类型 | 范围 | 示例 |
---|---|---|
局部作用域 | 函数内部或代码块{} 内 | 函数形参、局部变量 |
全局作用域 | 从定义处到文件结束 | 全局变量、函数名 |
(2) 核心规则
先定义后使用:
printf("%d", num); // 错误!
int num = 10;
同作用域禁止重名:
int x = 5;
float x = 3.14; // 编译错误
无包含关系作用域:
void func1() { int a=1; }
void func2() { int a=2; } // 合法,互不影响
包含关系作用域:
int a = 10;
void func() {
int a = 20;
printf("%d", a); // 输出20(外层a被屏蔽)
}
3. 变量生存期
(1) 静态生存期
- 包含对象:全局变量、
static
修饰的变量 - 特性:
- 程序启动时创建,结束时销毁
- 未初始化时自动赋0值
static
的两种用途:
static int count = 0; // 限制作用域到本文件
void func() {
static int calls = 0; // 保留值且仅在函数内可见
}
(2) 动态生存期
- 包含对象:
auto
局部变量(默认) - 特性:
- 进入作用域时创建,离开时销毁
- 未初始化时值为随机垃圾数据
(3) 存储类别关键字
关键字 | 作用 | 示例 |
---|---|---|
auto | 默认局部变量(可省略) | auto int x; |
register | 建议编译器将变量存入寄存器 | register int i; |
static | 延长生命周期或限制作用域 | static int counter; |
extern | 声明外部定义的变量 | extern int global_var; |
4.练习
1.二维整型数组相关练习
int sum0Array2DEdge(int a[][4],int rows)//边缘求和
{
int cols = sizeof(a[0]) / sizeof(a[0][0]);
int i,j;
int sum =0;
for(i = 0;i < rows;++i)
{
for(j = 0;j < cols;++j)
{
if(i == 0 || j == 0 || i == rows - 1 || j == cols -1)
{
sum += a[i][j];
}
}
}
return sum;
}
void printArray2D(int a[][4],int rows) //遍历输出
{
int cols = sizeof(a[0]) / sizeof(a[0][0]);
int i,j;
int sum =0;
for(i = 0;i < rows;++i)
{
for(j = 0;j < cols;++j)
{
printf("%2d ",a[i][j]);
}
puts("\n");
}
}
void reverse(int a[],int len)//一维数组翻转
{
int i;
for(i = 0;i < len / 2;++i)
{
int t = a[i];
a[i] = a[len - i - 1];
a[len - i - 1] = t;
}
}
void reverse2D(int a[][4],int rows)//水平翻转
{
int i,j;
int cols = sizeof(a[0]) / sizeof(a[0][0]);
for(i = 0;i < rows;++i)
{
reverse(a[i],cols);
}
}
void advArray2D(int a[][4],int b[],int rows)//每一行平均值
{
int i = 0,j = 0;
for(i = 0;i < rows;++i)
{
int sum = 0;
for(j = 0;j < 4;++j)
{
sum += a[i][j];
}
sum = sum / 4;
b[i] = sum;
}
}
int main(void)
{
int a[][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
int sum = 0;
int rows = sizeof(a) / sizeof(a[0]);
//printArray2D(a,rows);
//sum = sum0Array2DEdge(a,rows);
//printf("%d\n",sum);
//reverse2D(a,rows);
//printArray2D(a,rows);
int b[3];
advArray2D(a,b,rows);
int i;
for(i = 0;i < 3;++i)
{
printf("%d\n",b[i]);
}
return 0;
}
2.二维字符型数组相关练习
#include <string.h>
void printStrings(char s[][100],int rows)//遍历输出
{
int i;
for(i = 0;i < rows;++i)
{
puts(s[i]);
}
}
void reverseStrings(char s[][100],int rows)//逆序
{
int i;
for(i = 0;i < rows / 2;++i)
{
char t[100];
strcpy(t,s[i]);
strcpy(s[i],s[rows - i - 1]);
strcpy(s[rows - i - 1],t);
}
}
void sortStrings(char s[][100],int rows)//插入排序
{
int i,j;
for(i = 0;i < rows - 1;++i)
{
for(j = i + 1;j < rows;++j)
{
if(strcmp(s[i],s[j]) > 0)
{
char t[100];
strcpy(t,s[i]);
strcpy(s[i],s[rows - i - 1]);
strcpy(s[rows - i - 1],t);
}
}
}
}
void maxOfStrings(char s[][100],int rows,char max[])//极值
{
strcpy(max,s[0]);
int i;
for(i = 1;i < rows;++i)
{
if(strcmp(max,s[i]) < 0)
{
strcpy(max,s[i]);
}
}
}
int binaryFindStrings(char s[][100],int rows,char n[])
{
int begin = 0;
int end = rows - 1;
int mid;
while(begin <= end)
{
mid = (begin + end) / 2;
if(strcmp(s[mid],n) > 0)
{
end = mid - 1;
}
else if(strcmp(s[mid],n) < 0)
{
begin = mid + 1;
}
else
{
break;
}
}
if(begin <= end)
{
return 1;
}
else
{
return -1;
}
}
int main(void)
{
char s[][100] = {"Hello","World","China"};
char max[100];
char n[100] = "China";
int rows = sizeof(s) / sizeof(s[0]);
//maxOfStrings(s,rows,max);
//puts(max);
//reverseStrings(s,rows);
//printStrings(s,rows);
//sortStrings(s,rows);
//printStrings(s,rows);
sortStrings(s,rows);
int i = binaryFindStrings(s,rows,n);
if(i > 0)
{
printf("Found\n");
}
else
{
printf("Eroor\n");
}
return 0;
}
5. 开发技巧
(1) Vim操作
- 解除鼠标限制:
:set mouse=a
- 分屏编辑:
:vsp fun.c " 垂直分屏
:sp test.h " 水平分屏
(2) 多文件编译
- 头文件声明:
// mylib.h
#ifndef MYLIB_H
#define MYLIB_H
extern void my_func(); // 声明函数
#endif
- 编译命令:
gcc main.c lib.c -o app # 联合编译多个.c文件
6.日历
详情在下面代码
https://gitcode.com/weixin_72612809/rili
总结
- 二维数组传参:必须显式传递维度信息(列数/行数)
- 作用域规则:严格遵循"就近原则",合理使用
static
控制可见性 - 生存期管理:
- 全局/静态变量:长期存在但增加内存占用
- 局部变量:高效但需注意生命周期
- 嵌入式优化:
- 慎用
register
(现代编译器自动优化) - 多文件开发优先使用头文件
- 慎用
关联知识:结合指针理解二维数组的内存布局