计算存储在 char 数组中的字符串的长度时,`strlen` 的奇怪输出

strange output of `strlen` when calculating the length of string which is stored in a char array

代码:

int main(int argc, char **argv) {
    char a[2] = "aa";
    printf("%lu\n", strlen(a)); //8
    return 0;
}

为什么它输出 8 而不是 2

Gcc 版本:

Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/include/c++/4.2.1
Apple LLVM version 10.0.1 (clang-1001.0.46.4)
Target: x86_64-apple-darwin18.7.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
int main(int argc, char **argv) {
    char a[2] = "aa";
    printf("%lu\n", strlen(a)); //8
    return 0;
}

strlen 需要一个以零结尾的字符串。 2 元素 char 数组 a 不是零终止的,因为您没有为零提供 space 。所以 strlen 继续计数,直到它 运行 在某处变为零。在您的情况下,它恰好是 a 数组末尾后 6 个字节。在所有情况下,即使是访问末尾的一个元素(即 a[2] - 这里的第三个元素)也是未定义的行为,并且可能以许多或多或少有趣的方式表现出来(或者有时也令人毛骨悚然) ).

有两个修复(至少),具体取决于您的意图:

  1. 使数组至少有 3 个元素长:然后它将适合零终止符,并且 strlen 将能够在超出数组末尾之前停止计数。

  2. 保持数组 2 个元素长。但是由于数组的大小是固定的,所以使用 sizeof(a) 而不是 strlen(a)sizeof 在编译时确定数组的大小,因为有关实际大小的信息并没有真正离开编译器。当程序完成编译并到达 运行 时,它无法再安全地确定该大小 - 如果您保持 a 两个字符长并使用 strlen,那就是。然后 sizeof 唯一 向程序提供该信息的方式(或通过使用魔术常量,即在其他地方粘贴另一个“2”或其等价物)。