代码块中的警告,"operation may be undefined"

warning in codeblocks, "operation may be undefined"

我收到警告,而不是错误,当我忽略警告并且 build/run 无论如何,我的代码似乎工作正常。不过我还是很担心,因为警告,或者我只是想了解一下。

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

void s_pfx(char pf, char *s){

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

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

    s[i] = pf;
}

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

警告是"warning: operation on 'i' may be undefined [-Wsequence-point]"

我可以使用

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

但我为什么要那样做呢?这似乎会耗尽时间,也许是纳秒,但它会加起来。

我不明白为什么编译器无法理解代码。这对我来说似乎很明确。我看了一些其他类似的 questions/answers 但这看起来简单多了。

求助!谢谢

错误确实在表达式 s[i] = s[-- i].

C 规范要求某些运算符充当 "sequence points" — 也就是说,它们的第一个操作数在第二个操作数之前被完全评估。但是,= 运算符不是 — 这意味着编译器可以按任何顺序计算表达式。

当您执行类似 i = i + 3 的操作时,这不是问题,因为不会评估赋值的左侧符号(它被写入,而不是读取)。但是你在那里使用指针。 s[i] 在 C 中的真正意思是 *(s + i);括号是语法糖。

所以你真的有 *(s + i) = *(s + --i) 在那里。该表达式在左侧读取 i(它必须计算总和以计算存储数据的地址)并在右侧写入 i--i).并且没有固定的求值顺序,因为=不是一个序列点。

这意味着读取可以在写入之前或之后进行。在那些情况下,C 标准表示该操作是 未定义,这意味着编译器可以使该代码分支执行任何操作。