代码块中出现警告,“操作可能未定义”

时间:2019-06-07 02:12:01

标签: c codeblocks

我得到一个警告,而不是一个错误,并且当我忽略警告并继续构建/运行时,我的代码似乎运行良好。不过,由于警告,我还是很担心,或者也许我只是想了解它。

此函数将单个char附加到字符串的开头。

void s_pfx(char pf, char *s){

    i = -1;
    while(s[++i]);
    s[i + 1] = '\0';

    while(i)
        s[i] = s[--i];

    s[i] = pf;
}

当我预先减少i时,警告在while循环中。 (我将i作为全局变量。)

警告是“警告:'i'上的操作可能未定义[-Wsequence-point]”

我可以通过使用

进行修复
while(i){
    s[i] = s[i - 1];
    i--;
}

但是为什么我必须那样做呢?似乎会吃掉时间,也许是十亿分之一秒,但它会累加起来。

我不明白为什么编译器无法理解代码。对我来说,这似乎很明确。我查看了其他一些类似的问题/答案,但这似乎简单得多。

帮助!谢谢。

1 个答案:

答案 0 :(得分:3)

错误确实存在于表达式s[i] = s[-- i]中。

C规范要求某些运算符充当“序列点”,也就是说,它们的第一个操作数要在第二个操作数之前得到完全评估。 =运算符不是-意味着编译器可以按任何顺序求值。

当您执行i = i + 3之类的操作时,这不是问题,因为未评估分配的左手符号(将其写入,而不读取)。但是您在那里使用指针。 s[i]在C中的真正含义是*(s + i);方括号是语法糖。

因此,您确实有*(s + i) = *(s + --i)。该表达式在左侧读取i(它必须求和以计算出要存储数据的地址),并在右侧写入i({{1} }。而且没有固定的求值顺序,因为--i不是序列点。

这意味着读取可以在写入之前或之后进行。在这种情况下,C标准说该操作是 undefined ,这意味着编译器可以使该代码的分支实际上可以执行任何操作。