C for循环中的条件检查

C for循环中的条件检查,c,for-loop,conditional-statements,C,For Loop,Conditional Statements,考虑以下代码: int main() { int i; int ints[3]; ints[0] = 0; ints[1] = 1; ints[2] = 2; for(i = 0; (ints[i])<4 && i<3; i++) { printf("%d\n", ints[i]); } } int

考虑以下代码:

int main()
    {
        int i;
        int ints[3];
        ints[0] = 0;
        ints[1] = 1;
        ints[2] = 2;

        for(i = 0; (ints[i])<4 && i<3; i++)
        {
            printf("%d\n", ints[i]);
        }
    }
intmain()
{
int i;
int-int[3];
ints[0]=0;
ints[1]=1;
ints[2]=2;

对于(i=0;(ints[i])最好执行
i<3&&ints[i]<4
,因为语句的第二部分仅在第一部分为真时才计算。按照您的方式,它将查找不存在的
ints[3]

在该循环的最后一次迭代中,表达式
ints[i]按照编写循环的方式,您的代码将尝试读取不存在的数组元素ints[3]。这是未定义的行为;结果是任何事情都可能发生。现在整个互联网都在骚动,因为OpenSSL中的一些代码调用了未定义的行为。

这样做是不好的,因为
ints[3]
确实会被访问。现在,由于这是C,您不会得到错误(很遗憾),但您永远无法确定结果会是什么


交换语句将解决问题,因为&&运算符已优化,因此如果第一个条件为false,它不会计算第二个条件。

for关键字按以下方式展开:

int i;
for(i = 0; i < 2; i++)
    dothing();
虽然这很好,但测试的顺序存在问题:

(ints[i] < 4) && (i < 3)
(ints[i]<4)和&(i<3)
在使用数组索引之前,应始终首先检查它们是否有效:

i = 0:
    ints[0] < 4 && 0 < 3
i = 1:
    ints[1] < 4 && 1 < 3
i = 2:
    ints[2] < 4 && 2 < 3
i = 3:
    ints[3] < 4 && 3 < 3 /* illegal access to ints[3] */
i=0:
整数[0]<4&&0<3
i=1:
整数[1]<4&&1<3
i=2:
整数[2]<4&&2<3
i=3:
ints[3]<4&&3<3/*非法访问ints[3]*/

一般的经验法则是,除非有更好的排序理由,否则总是尝试按成本顺序排列条件,例如优先级:在这种情况下,
i<3
是两个测试中较便宜的一个,加上它是对可以访问的
int
元素的约束,因此检查索引时应该有更高的优先级ity-在使用它测试
ints[i]
任何东西之前,您应该检查它。

循环终止,这没关系。但是您访问的区域超出了允许的范围。这是未定义的行为。您可以随时获得分段。但您很幸运


试着把
iAs Matt说,这种行为在C中是未定义的。因此这将取决于编译器如何处理这一代码序列。在我上一次工作的地方,我们为16位系统编写了一些C,并且我们使用的特定编译器有数组大小限制。然而,按照编译器的工作方式,我们可以对两个数组进行malloc next指向彼此,第一个的指针在达到大小限制后会溢出到第二个。除非您必须这样做,否则这不是您真正想要做的事情,也没有办法解决。我应该像另一个答案建议的那样交换语句吗?这仍然不安全吗?是否需要检查“&&”条件自始至终是自始至终还是依赖于编译器?//编辑:发布时没有看到前面的注释,哪种类型的注释回答了这个问题。如果交换语句,则代码是安全的。
&&
是C中的短路运算符。在访问
ints[3]之前,条件
i<3
变为false
;循环在
i<3
计算为false后立即终止。因此,对
int[]的所有访问
在数组中,行为已定义。代码是否清晰和可维护是另一回事。只想补充一下:经验法则是避免像瘟疫一样的未定义的行为,除非您的特定编译器对此有定义的结果,并且您有很好的理由这样做。&&运算符会做一件事ndred percent reliable执行第一个测试,如果该测试为假,则根本不执行第二个测试。感谢您的回答,我最初确实将iTo放在了最后一个位置-它们遵循传统的C短路规则;当C计算逻辑表达式时,
(x==2&&y==3)| |(z==1)
,它尝试做最小的必要功;因此,如果x为1,它不会检查y,但会测试z;如果x为2,y为3,它不会检查z,但如果x为2,y为4,它会检查x、y和z。
(ints[i] < 4) && (i < 3)
i = 0:
    ints[0] < 4 && 0 < 3
i = 1:
    ints[1] < 4 && 1 < 3
i = 2:
    ints[2] < 4 && 2 < 3
i = 3:
    ints[3] < 4 && 3 < 3 /* illegal access to ints[3] */
for(i = 0; i<3 && (ints[i])<4; i++)