printf("y = %s\n", y);
在这种情况下,是未定义的行为。换句话说,你很幸运——也许你在命中 NUL 之前打印了一些不可见的字符,也许由于堆栈对齐,数组后面有一个零,也许星星是正确的。
我通常不会详细说明“这是 UB,请勿触摸”,但我感到奇怪的是被迫这样做。
看,这是你的程序:
#include <stdio.h>
int main() {
char y[4] = {'a', 'a', 'a', 'a'};
char z[4] = {'b', 'b', 'b'};
printf("y = %s\n", y);
printf("z = %s\n", z);
}
现在我将使用我的特殊编译器标志来编译它:
$ cc -O3 so15727258.c -o so15727258 -fstack-protector-all -Wall
并运行它:
$ ./so15727258
y = aaaa?>A??0F
z = bbb
哎呀,哈哈,这完全是垃圾。更好的是,由于堆栈保护器,它是随机垃圾,所以它甚至(简单)不是确定性的。哇!
还是不服气?特殊的编译器标志对你来说太奇怪了吗?尝试
#include <stdio.h>
int bar() {
char x[4096];
}
int foo() {
char y[4] = {'a', 'a', 'a', 'a'};
char z[4] = {'b', 'b', 'b'};
printf("y = %s\n", y);
printf("z = %s\n", z);
}
int main() {
bar();
foo();
}
编译它:
$ cc so15727258.c -o so15727258 -Wall
并运行它:
$ ./so15727258
y = aaaa?????ic?
z = bbb
还是完全垃圾!请记住——这些例子都是说明性的。当然这是未定义的行为,所以你可能会得到一些完全不同的结果,然后回到这里告诉我“但是 XYZ 有效”。这就是未定义行为的定义。