【问题标题】:Is this undefined behavior in C? (c=x) + (c==y)这是 C 中未定义的行为吗? (c=x) + (c==y)
【发布时间】:2012-06-23 19:02:42
【问题描述】:

我有一些示例代码会引发此警告:

main.c: In function ‘getline_’:
main.c:30:32: warning: operation on ‘c’ may be undefined [-Wsequence-point]

在这个特定的练习中,我要避免使用 ||&& 运算符,但这似乎不会产生未定义的行为。编译器消息 is 只是一个警告,但我想知道以了解情况。这段代码真的会产生未定义的行为吗?

 24 int getline_( char s[], int limit)
 25 {
 26     int i, c;
 27     i=0;
 28     for( i=0; (i<limit-1) + ((c=getchar())!='\n') + (c!=EOF) == 3; i++){
 29            s[i]=c;
 30     }
 31     if( c == '\n' ){
 32         s[i]=c;
 33         i++;
 34     }
 35     s[i]='\0';
 36     return i;
 37 }

在我的基本测试中似乎工作正常。

编辑:根据评论更新标题,谢谢 pst。

【问题讨论】:

  • 仅仅因为“它在这里工作”并不意味着它是定义的行为。 UB 可能是您一直观察到的行为......(不过,它可能涉及将仓鼠飞到其他地方)
  • 这正是我想确定并来到这里的原因。 :)
  • 考虑提炼测试用例(可以生成更少的警告)并将其合并到标题中。它基本上归结为:(c=x) + (c==y)

标签: c undefined-behavior


【解决方案1】:

这是未指定的行为:

(i&lt;limit-1) + ((c=getchar())!='\n') + (c!=EOF) == 3

在 C 中未指定序列点之间表达式的求值顺序。如果对 c 的赋值发生在与 EOF 的相等性检查之前,则未指定。

除了未指定的行为之外,它也是未定义的行为,因为它违反了序列点规则,尤其是这个:

(C99, 6.5p2) "此外,先验值应只读以确定要存储的值。"

【讨论】:

  • Pedantic nitpick:但警告说它的未定义行为不是未指定行为,所以...
  • 自我注意,需要一点 lisp。感谢您指出了这一点!只是等待计时器消失接受...
  • 那么,我是否正确地将该序列点规则解释为在该表达式中进行变量赋值是无效的?抱歉,如果这似乎是另一个愚蠢的问题,这里是新手...
  • 恭喜,因为您认为确实是正确的 :) 这就是答案开始时应该说的。
  • 不仅仅是未指定;它是未定义的。因为c在序列点之间同时被写入和读取,并且读取的值用于确定要写入的值以外的目的,所以它是UB。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-03
  • 1970-01-01
  • 2011-06-22
  • 1970-01-01
  • 2011-07-20
相关资源
最近更新 更多