二维字符数组与函数(声明、作用域、生存周期、存储)

📅 2026/7/30 4:36:56
二维字符数组与函数(声明、作用域、生存周期、存储)
1. 二维字符型数组二维字符数组是C语言中处理字符串数组的常用数据结构可以看作是一个字符串列表。1.1 定义与初始化// 方式1指定行数和列数 char names[3][10] {Alice, Bob, Charlie}; // 方式2省略行数由初始化列表决定 char fruits[][8] {apple, banana, orange}; // 方式3逐个字符初始化 char matrix[2][3] {{a, b, c}, {d, e, f}};1.2 内存布局与访问二维字符数组在内存中是连续存储的。对于char arr[3][10]它占用30个连续字节每行10个字符。#include stdio.h int main() { char cities[3][20] {Beijing, Shanghai, Guangzhou}; // 访问单个字符 printf(第一个城市的第一个字符: %c\n, cities[0][0]); // B // 访问整个字符串 printf(第二个城市: %s\n, cities[1]); // Shanghai // 遍历所有字符串 for (int i 0; i 3; i) { printf(城市%d: %s\n, i 1, cities[i]); } return 0; }1.3 与指针数组的区别二维字符数组存储的是实际字符数据而字符指针数组存储的是字符串常量的地址。// 二维字符数组 - 可修改内容 char arr[2][10] {hello, world}; arr[0][0] H; // 允许修改 // 字符指针数组 - 指向字符串常量 char *ptr_arr[] {hello, world}; // ptr_arr[0][0] H; // 错误试图修改字符串常量2. 函数的声明与定义2.1 函数声明原型函数声明告诉编译器函数的名称、返回类型和参数列表但不包含函数体。// 函数声明通常在头文件或文件开头 int add(int a, int b); void print_array(char arr[][10], int rows); double calculate_average(double numbers[], int count);2.2 函数定义函数定义包含函数的具体实现。// 函数定义 int add(int a, int b) { return a b; } // 处理二维字符数组的函数 void print_strings(char strings[][20], int count) { for (int i 0; i count; i) { printf(字符串%d: %s\n, i 1, strings[i]); } }3. 作用域Scope作用域决定了标识符变量、函数名在程序中的可见范围。3.1 局部作用域void function1() { int x 10; // x只在function1中可见 printf(x %d\n, x); } void function2() { // printf(x %d\n, x); // 错误x在function2中不可见 int x 20; // 这是另一个x与function1中的x无关 }3.2 全局作用域#include stdio.h int global_var 100; // 全局变量从声明处到文件末尾都可见 void func_a() { printf(func_a: global_var %d\n, global_var); // 可以访问 global_var 200; // 可以修改 } void func_b() { printf(func_b: global_var %d\n, global_var); // 可以访问值为200 } int main() { func_a(); func_b(); return 0; }3.3 块作用域int main() { int outer 5; { int inner 10; // inner只在这个块内可见 printf(inner %d\n, inner); printf(outer %d\n, outer); // 可以访问外层变量 } // printf(inner %d\n, inner); // 错误inner已不可见 for (int i 0; i 3; i) { int loop_var i * 2; // loop_var只在循环体内可见 printf(循环%d: loop_var %d\n, i, loop_var); } // printf(loop_var %d\n, loop_var); // 错误 return 0; }4. 生存周期Lifetime生存周期指变量在内存中存在的时间。4.1 自动存储期局部变量void demo_auto() { int auto_var 10; // 进入函数时创建函数结束时销毁 auto_var; printf(auto_var %d\n, auto_var); } // auto_var在这里被销毁 int main() { demo_auto(); demo_auto(); // 每次调用都创建新的auto_var return 0; }4.2 静态存储期static变量void counter() { static int count 0; // 只初始化一次函数结束后仍存在 count; printf(调用次数: %d\n, count); } int main() { counter(); // 输出: 调用次数: 1 counter(); // 输出: 调用次数: 2 counter(); // 输出: 调用次数: 3 return 0; }4.3 动态存储期malloc分配#include stdlib.h int main() { int *ptr (int*)malloc(5 * sizeof(int)); // 动态分配内存 if (ptr ! NULL) { for (int i 0; i 5; i) { ptr[i] i * 10; } // 使用完毕后必须手动释放 free(ptr); ptr NULL; // 避免野指针 } return 0; }5. 存储类别5.1 auto默认void func() { auto int x 10; // auto可省略默认就是auto int y 20; // 等价于 auto int y 20 }5.2 registervoid optimize_loop() { register int i; // 建议编译器将i放入寄存器编译器可能忽略 for (i 0; i 1000000; i) { // 频繁使用的循环变量 } }5.3 static// 文件作用域的static变量 static int file_static 100; // 只在当前文件可见 void preserve_state() { static char buffer[100]; // 函数调用间保持值 static int initialized 0; if (!initialized) { strcpy(buffer, 初始值); initialized 1; } printf(buffer: %s\n, buffer); }5.4 extern// file1.c int global_counter 0; // file2.c extern int global_counter; // 声明在其他文件中定义的变量 void increment_counter() { global_counter; }6. 综合示例二维字符数组与函数#include stdio.h #include string.h // 函数声明 void print_string_array(char arr[][20], int size); void sort_strings(char arr[][20], int size); int find_string(char arr[][20], int size, const char *target); // 全局变量 static int call_count 0; int main() { char students[][20] {ZhangSan, LiSi, WangWu, ZhaoLiu}; int count 4; call_count; printf( 程序第%d次运行 \n, call_count); printf(原始数组:\n); print_string_array(students, count); sort_strings(students, count); printf(\n排序后数组:\n); print_string_array(students, count); int pos find_string(students, count, LiSi); if (pos ! -1) { printf(\n找到 LiSi 在位置: %d\n, pos); } return 0; } // 函数定义打印字符串数组 void print_string_array(char arr[][20], int size) { for (int i 0; i size; i) { printf( [%d] %s\n, i, arr[i]); } } // 函数定义冒泡排序字符串数组 void sort_strings(char arr[][20], int size) { char temp[20]; for (int i 0; i size - 1; i) { for (int j 0; j size - 1 - i; j) { if (strcmp(arr[j], arr[j 1]) 0) { strcpy(temp, arr[j]); strcpy(arr[j], arr[j 1]); strcpy(arr[j 1], temp); } } } } // 函数定义查找字符串 int find_string(char arr[][20], int size, const char *target) { for (int i 0; i size; i) { if (strcmp(arr[i], target) 0) { return i; } } return -1; }7. 关键要点总结二维字符数组用于存储多个字符串内存连续可修改内容函数声明告诉编译器函数接口便于类型检查作用域决定标识符的可见范围局部、全局、块作用域生存周期决定变量的存在时间自动、静态、动态存储类别auto默认、register、static、extern最佳实践合理使用static保持状态及时释放动态内存理解这些概念对于编写模块化、可维护的C程序至关重要。二维字符数组结合函数的使用是处理字符串集合的常见模式。