如果我使用指针迭代一个字符数组并以这种方式声明:
char my_ary[3] = { 'A', 'B', 'C' };
char *my_p = my_ary;
while(*my_p){
printf("value of pointer is %c\n", *my_p);
my_p++;
}
我得到了值和一些垃圾:
value of pointer is A
value of pointer is B
value of pointer is C
value of pointer is �
value of pointer is �
value of pointer is u
value of pointer is �
value of pointer is �
value of pointer is
另一方面,如果我将数组声明为静态,我不会得到垃圾:
static char my_ary[3] = { 'A', 'B', 'C' };
char *my_p = my_ary;
while(*my_p){
printf("value of pointer is %c\n", *my_p);
my_p++;
}
value of pointer is A
value of pointer is B
value of pointer is C
为什么静态关键字会影响这种特殊情况?
答案 0 :(得分:0)
您正在将指针移出数组边界,这是未定义的行为,因此您不能指望它。如果你希望这个循环起作用,你必须在结尾处有一个NUL字符('\0'
)或迭代到数组的长度。在这种情况下,static
只意味着值将保留在函数调用之间。这可能会影响编译器管理内存的方式,但不知道编译器的细微之处是无法分辨的。
答案 1 :(得分:0)
两者都是未定义的行为,因为没有用于停止while
循环的尾随零终止符。只要my_p
转到my_ary + 3
您的解除引用,就会触发UB。
声明为static
的变量只要整个程序运行就具有生命周期,并且它们存储在与具有自动寿命的变量不同的位置,其中可能存在更多的零(因为{{1}如果未指定,变量将初始化为零),因此您的循环可以在static
结束。但同样,访问越界是UB,不要依赖它。
如果你这样写,你可能会观察到不同的输出:
my_ary + 3
这是我的测试结果。
我特意选择了8的大小以避免填充中的自动零(由于内存对齐)。你的静态数组停止循环可能是因为在它的邻接中存在其他类型的静态变量,在它们之间留下零初始化的填充,从而终止你的循环。
当您定义指向字符串文字的指针时,行为是明确定义的,因为字符串文字在它们的末尾有一个隐式空字符。例如:
static char my_ary[8] = "ABCDEFGH";
因此,当你的指针到达空终止符时,循环停止。
答案 2 :(得分:0)
我没有得到垃圾: ..
那又怎样?你认为那是对的吗?那就是undefined behavior。
这里放static
然后获得正确的输出让你想到 - 如果这是正确的。 嗯,这不是。
char my_ary[3] = { 'A', 'B', 'C' };
你不喜欢\0
这就是你只存储3个字符的原因。 \0
没有空间。所以这个循环永远不会终止。
static char my_ary[3] = { 'A', 'B', 'C' };
仍然采用相同的逻辑。在您的情况下,A
.. C
之后的下一个字节是0
。这就是循环终止的原因。这仍然是未定义的行为。我们不知道下次运行它会发生什么。
如果你这样做
static char my_ary[3] = "ABC";
再次
my_ary[3]
等效{'A','B','C'}
。是的,没有\0
。因此,如果你传递了null终止的char数组,那么它将再次调用未定义的行为。