是“*p = ++(*q)”吗?当 p 和 q 指向同一个对象时未定义?
在阅读了有关序列点的内容后,我了解到 i = ++i
是未定义的。
那么这段代码怎么样:
int i;
int *p = &i;
int *q = &i;
*p = ++(*q); // that should also be undefined right?
假设 p 和 q 的初始化是否取决于某些(复杂的)条件。 它们可能指向同一个对象,就像上面的例子一样。 会发生什么?如果未定义,我们可以使用什么工具来检测?
编辑:如果两个指针不应该指向同一个对象,我们可以使用 C99 限制吗? 这就是‘严格’的意思吗?
after reading about sequence points, I learned that i = ++i
is undefined.
So how about this code:
int i;
int *p = &i;
int *q = &i;
*p = ++(*q); // that should also be undefined right?
Let's say if initialization of p and q depends on some (complicated) condition.
And they may be pointing to same object like in above case.
What will happen? If it is undefined, what tools can we use to detect?
Edit: If two pointers are not supposed to point to same object, can we use C99 restrict?
Is it what 'strict' mean?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
是的,这是未定义的行为——您对一个对象进行了两次修改,而它们之间没有序列点。不幸的是,自动检查这一点非常困难——我能想到的最好的办法就是在这之前添加assert(p != q),这至少会给出一个干净的运行时错误,而不是更糟糕的情况。在一般情况下,在编译时检查这一点是不可判定的。
Yes, this is undefined behavior -- you have two modifications of an object without a sequence point between them. Unfortunately, checking for this automatically is very hard -- the best I can think of is adding
assert(p != q)
right before this, which will at least give a clean runtime fault rather than something worse. Checking this at compile time is undecidable in the general case.最好的工具不是检测,而是首先避免这种情况,那就是使用良好的编程实践。避免副作用,并且每个作业的写入次数不超过一次。没有什么问题
The best tool not to detect, but to avoid this in the first place is to use good programming practice. Avoid side-effects and do no more than one write per assignment. There is nothing wrong with
表达式与 i=++i 相同。唯一可以检测到它的工具是你的头。在 C 语言中,权力伴随着责任。
The expression is the same as i=++i. The only tool that can detect it is your head. In C with power comes responsibility.
第 5 章表达式
第 4 点:
因此,这是未定义的行为:
在“Bad Line”中,标量对象“i”在表达式求值期间多次更新。仅仅因为对象“i”被间接访问并不会改变规则。
Chapter 5 Expressions
Point 4:
As a result this is undefined behavior:
In 'Bad Line' the scalar object 'i' is update more than once during the evaluation of the expression. Just because the object 'i' is accessed indirectly does not change the rule.
这是个好问题。您强调的一件事是“序列点”,引用自此 site< /a>
更进一步,上面的表达式类似地相同,所以行为是未定义,至于追踪它的工具,为零,当然有splint 举个例子,但它是一个 C 标准,所以也许在我还没有听说过的工具中存在一个隐藏选项,也许 Gimpel 的 PC Lint 或 Riverblade 的 Visual lint 可能会对您有所帮助,尽管我承认它没有提及任何有关跟踪这方面未定义行为的内容。
顺便说一句,GCC 的编译器版本 4.3.3 有这个选项
-Wsequence-point
作为标记警告的一部分。这在我的 Slackware 13.0 盒子上...它只是表明,该代码可能看起来没问题肉眼可以编译得很好,但以后可能会引起头痛,最好的方法是进行代码审查,可以发现编译器可能无法识别的东西,这是最好的选择武器!
That's a good question. The one thing you have highlighted is 'sequence points', to quote from this site
And further more, that expression above is similarly the same, so the behaviour is undefined, as for tools to track that down, is zero, sure there's splint to name one as an example, but it's a C standard, so maybe there's a hidden option in a tool that I have not yet heard of, maybe Gimpel's PC Lint or Riverblade's Visual lint might help you although I'll admit it does not mention anything about tracking down undefined behaviour in this regard.
Incidentally, GCC's compiler version 4.3.3 has this option
-Wsequence-point
as part of flagging up warnings..this is on my Slackware 13.0 box...It just shows, that code may look ok to the naked eye and will compile just fine, but can cause headaches later on, the best way to do it is to have code review that can spot out things a compiler may not pick up on, that is the best weapon of choice!