C语言中strlen(&t[])的工作机制及实验结果困惑
首先要纠正你两个关键误解,这是导致你困惑的核心原因:
1. 未初始化的数组元素不是默认的0!
在第一个实验中:
char t[10]; strcpy(t, "abcd");
strcpy只会把字符串"abcd"及其末尾的终止符'\0'复制到t中,也就是t[0]='a'、t[1]='b'、t[2]='c'、t[3]='d'、t[4]='\0'。而t[5]到t[9]属于未初始化的栈内存,里面存储的是随机的垃圾值(不是你假设的0)。
strlen(&t[5])的作用是从t[5]的位置开始,逐个字节查找第一个'\0',统计之前的字符数。你得到返回值3纯粹是巧合——刚好在t[5]之后的第3个位置遇到了一个随机出现的'\0'。如果换个环境运行,这个结果可能完全不同,甚至程序崩溃,因为访问未初始化内存属于未定义行为的一部分。
2. strcpy会写入终止符,数组越界属于未定义行为
在第二个实验中:
char t[10]; strcpy(t, "abcdefghij");
你声明的t是长度为10的字符数组,索引范围是0~9。但字符串"abcdefghij"本身有10个字符,加上strcpy必须添加的终止符'\0',总共需要11个字节的空间。这就导致strcpy会把'\0'写入到t[10]的位置——这已经超出了数组t的范围,属于数组越界访问,是C语言中的未定义行为。
此时strlen(&t[5])返回5,是因为t[5]到t[9]是'f'到'j',而越界写入的t[10]是'\0',所以从t[5]开始数,刚好有5个非'\0'字符。但这只是未定义行为下的巧合:如果t[10]的位置原本有其他数据,或者编译器优化改变了内存布局,结果可能完全不同,甚至程序崩溃。
至于为什么没有编译错误?因为C语言标准不要求编译器检查数组越界(很多编译器在开启高警告级别,比如-Wall -Wextra时会给出警告,但不会当作错误阻止编译)——这是C语言的灵活性带来的风险,需要开发者自己注意内存边界。
总结一下
strlen的工作逻辑是:从给定地址开始,直到遇到第一个'\0',返回中间的字符数,不会检查数组边界。- 未初始化的栈数组元素是随机值,不是默认的0。
- 数组越界是未定义行为,任何结果都可能发生,不要依赖这种巧合。
内容的提问来源于stack exchange,提问作者Pero Alex

