int i, a[7] = {-6, -4, -2, 0, 2, 4, 6};
for (i = 0; i < 4 || a[i]; i++)
putchar('*');
这个循环对我来说没有意义,因为它打印出了8 *&#39; s。这是C.
据我所知:
0 < 4 || -6
⟶*
1 < 4 || -4
⟶*
2 < 4 || -2
⟶*
3 < 4 || 0
⟶*
4 < 4 || 2
⟶*
5 < 4 || 4
⟶*
6 < 4 || 6
⟶*
到目前为止,这就是7星......在此之后
7 < 4 || '\0'
⟶*
这是一个类似的问题,打印出5颗星:
int i, a[2] = {-6, -4};
for (i = 0; i < 4 || a[i]; i++)
putchar('*');
我再也不明白它最后一次做了什么。
当它到达4 < 4 || ?
时,它不应该中断吗?
答案 0 :(得分:2)
此代码具有未定义的行为,因为它将访问数组外部的元素。如果将代码更改为以下内容,则可以看到此行为:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i, a[7] = {-6, -4, -2, 0, 2, 4, 6};
for (i = 0; i < 4 || a[i]; i++) {
printf("Accessing element: %d\n", i);
putchar('*');
}
}
在我的机器上,我得到以下输出:
Accessing element: 0
*Accessing element: 1
*Accessing element: 2
*Accessing element: 3
*Accessing element: 4
*Accessing element: 5
*Accessing element: 6
*Accessing element: 7
*Accessing element: 8
*
这是访问9个元素(索引8是基于零的索引数组的元素9)。一旦你有未定义的行为,所有赌注基本上都是关闭的。程序也可能循环,直到达到分段错误。
当i == 4
或i
大于4时,它不会中断,因为a[i]
为真,因此i < 4 || a[i]
也是如此。 a[i]
在数组长度之前是正确的,然后你访问数组之外的东西(第8个元素,索引7)然后你有未定义的行为。
答案 1 :(得分:1)
您的代码调用undefined behaviour,因为循环条件是伪造的并导致访问超出其边界的数组。
请记住,没有边界检查由语言完成的数组或C中数组末尾的任何隐式 null 。许多无效代码编译得很好。作为程序员,您有责任确保您的代码有效。
正确的循环条件将确保不在其边界外访问数组:
for (i = 0; i < (sizeof a/sizeof a[0]) && a[i]; i++)
putchar('*');
答案 2 :(得分:0)
整数被视为&#34; true&#34;如果它不是零。在你的第一个例子中所有的情况,只要看到[I],那个值就非零,并且任何真实的都是真的。
(@ CyberSpock更详细地解释了这一点)
答案 3 :(得分:0)
int i, a[7] = {-6, -4, -2, 0, 2, 4, 6};
for (i = 0; i < 4 || a[i]; i++)
如果你看一下情况
i < 4 || a[i]
这意味着如果 i
小于4,则表达式为真,即数组[0-3]处的元素为真 OR 如果a[i]
不为0(a[i]
是a[i] != 0
的缩写形式)
数组的元素为零,它位于[3]但无论如何都要打印,因为该位置的其他部分或条件为真:i < 4
当处理这样的数组时,最好知道数组的大小,并将其作为最大值,即使你想要打破一个特定的值。
int N=sizeof(a)/sizeof(a[0])
或
#define N 7
for (i = 0; i < N && a[i]; i++)
这将阻止您从堆栈中读取随机值(在本例中)。