下面的 C 代码将生成 char 数组,但显式添加或不添加 Null 字符。结果在两个编译器中是出乎意料的,我不知道为什么我们甚至必须显式添加 Null 字符?
//
// stringBugorNot.c
//
//
//
#include <string.h>
#include <stdio.h>
int main(void)
{
char aString[3] = {'a', 'b','c'};
char bString[4] = {'a', 'b', 'c', '\0'};
printf("\n");
printf("len of a is: %lu\n", strlen(aString));
printf("len of b is: %lu\n", strlen(bString));
printf("\n");
//Portion A
printf("last element of a is: '%c'\n", aString[strlen(aString)]);
printf("last element of b is: '%c'\n", bString[strlen(bString)]);
printf("\n");
//Portion B
printf("last element of a is: '%c'\n", aString[strlen(aString) - 1]);
printf("last element of b is: '%c'\n", bString[strlen(bString) - 1]);
}
评论
+clang 会给出运行时错误,因为“aString”越界..是有道理的 +gcc 不会给出任何错误,只是按照预期输出“无”null。但也许 gcc 更聪明,为我添加了 null ?实际内存大小是否不同?
<小时/>Clang 输出 ---->
a 的长度为:3
b 的长度为:3
bugOrNot.c:16:41:运行时错误:索引 3 超出类型“char [3]”的范围
a 的最后一个元素是:''
b 的最后一个元素是:''
a 的最后一个元素是:'c'
b 的最后一个元素是:'c'
<小时/>GCC 输出 ---->
a 的长度为:9
b 的长度为:3
a 的最后一个元素是:''
b 的最后一个元素是:''
a 的最后一个元素是:''
b 的最后一个元素是:'c'
最佳答案
您看到的意外行为在 C 标准中称为未定义行为 (UB):
- 在
aString
上调用strlen
是 UB,因为没有 null 终止 - 在未定义索引处取消引用
aString
为 UB,除非索引为 0、1 或 2 - gcc 可能会通过在 4 字节边界对齐
bString
无意中插入空终止符。但这并没有改变它仍然是 UB 的事实。
关于C 编译器差异? Char 中的 NUL 控制字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52012445/