views:

214

answers:

5

Hi, 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?

+2  A: 

The expression is the same as i=++i. The only tool that can detect it is your head. In C with power comes responsibility.

spbfox
+12  A: 

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.

Chris Dodd
+1  A: 

That's a good question. The one thing you have highlighted is 'sequence points', to quote from this site

why you cannot rely on expressions such as: a[i] = i++; because there is no sequence point specified for the assignment, increment or index operators, you don't know when the effect of the increment on i occurs.

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!

tommieb75
A: 

Chapter 5 Expressions

Point 4:

Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified. Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored. The requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full expression; otherwise the behavior is undefined.

[ Example:
  i = v[i ++];           / / the behavior is undefined
  i = 7 , i++ , i ++;    / / i becomes 9
  i = ++ i + 1;          / / the behavior is undefined 
  i = i + 1;             / / the value of i is incremented
—end example ]

As a result this is undefined behavior:

int i;
int *p = &i;
int *q = &i;
*p = ++(*q);   // Bad Line

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.

Martin York
Might want to say Chapter 5 of what.
Kinopiko
@Kinopiko: I will give you two guesses.
Martin York
@Martin: thanks very much but I don't want to make two guesses, or any guesses at all for that matter.
Kinopiko
@Kinopiko: The only thing that is ever quoted in answer to a C++ question would be the C++ standard. If there were a discrepancy between the standards I would specify the exact version but since they are all the same it is redundant.
Martin York
@Martin York: Thanks, I didn't realize either that this was a C++ question or that the only possible thing to quote in an answer to a C++ question would be that.
Kinopiko
+2  A: 

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

*q += 1;
*p = *q;
Secure