【问题标题】:warning in codeblocks, "operation may be undefined"代码块中的警告,“操作可能未定义”
【发布时间】:2019-06-07 02:12:01
【问题描述】:

我收到的是警告,而不是错误,当我忽略警告并无论如何构建/运行时,我的代码似乎工作得很好。不过,我仍然担心,因为警告,或者我只是想了解它。

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

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--;
}

但是为什么我必须这样做呢?看起来这会消耗时间,也许是纳秒,但它会加起来。

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

帮助!谢谢。

【问题讨论】:

  • 这就是你不会像那样滥用递增和递减运算符的原因之一。它不仅难以阅读,而且有时会出现未定义的行为,就像这种情况一样。
  • 关于:while(s[++i]); s[i + 1] = '\0'; 您的问题中没有任何内容表明保存传入参数 's[]' 的缓冲区(至少)比包含的字符串长一个字节。所以这可能会超过输入缓冲区的末尾
  • @user3629249,是的,我一直在关注这一点。我的字符串都是 malloc'd 到 100,当我需要提高它时,我会通过我的输出知道。谢谢。

标签: c codeblocks


【解决方案1】:

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

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

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

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

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

【讨论】:

    猜你喜欢
    • 2014-09-13
    • 1970-01-01
    • 2012-07-29
    • 2011-09-28
    • 2021-12-15
    • 2023-03-16
    • 1970-01-01
    • 1970-01-01
    • 2015-01-21
    相关资源
    最近更新 更多