1. 字符型二维数组深度解析
1.1 基础概念与内存布局
字符型二维数组本质上是"数组的数组"——每个元素本身又是一个一维字符数组。这种结构在内存中按行优先顺序连续存储,例如char str[100][10]声明了一个能存储100个字符串的数组,每个字符串最大长度为9个字符(需预留1字节存放'\0'终止符)。
内存布局示例:
code复制str[0][0] str[0][1] ... str[0][9] | str[1][0] ... str[1][9] | ... | str[99][0] ... str[99][9]
这种连续存储特性带来两个重要特征:
str[i]实际上是指向第i行首字符的指针常量- 相邻字符串的内存地址间隔等于第二维声明的大小(上例中间隔10字节)
注意:
char str[100][10]与char *str[100]有本质区别,前者是连续内存块,后者是指针数组,每个元素需要单独分配内存。
1.2 初始化与操作细节
安全初始化方案:
c复制// 完全初始化(推荐)
char str[3][10] = {
{'h','e','l','l','o','\0'}, // 显式终止符
{'w','o','r','l','d','\0'},
{0} // 全零初始化
};
// 部分初始化(未显式初始化的元素自动清零)
char str[3][10] = {"hello", "world"};
常见操作陷阱:
- 越界写入是这类数组最常见错误:
c复制char str[3][5] = {"linux", "mac"}; // 危险!"linux"需要6字节空间
- 输入时应始终指定最大长度:
c复制scanf("%4s", str[0]); // 安全:最多读取4个字符(留1位给\0)
fgets(str[1], sizeof(str[1]), stdin); // 更安全的替代方案
- 字符串比较必须使用strcmp而非==:
c复制if(strcmp(str[0], "exit") == 0) // 正确
if(str[0] == "exit") // 错误!比较的是地址而非内容
``
