Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is ++*ptr++ undefined behaviour in c++?

I have been asked the following question in a test (I didn't want to write it myself. The test asked it. I know its bad code still) about evaluating ++*ptr++

int Ar[ ] = { 6 , 3 , 8 , 10 , 4 , 6 , 7} ; int *Ptr = Ar  ; cout<<++*Ptr++  ; 

However, I suspect this is undefined behavior since it can be both (++*ptr)++ or ++(*ptr++). Is it? I am not too well acquainted with documentation so I couldn't find anything.

like image 584
Harmonic Avatar asked Dec 20 '18 18:12

Harmonic


People also ask

What are undefined behavior in C?

So, in C/C++ programming, undefined behavior means when the program fails to compile, or it may execute incorrectly, either crashes or generates incorrect results, or when it may fortuitously do exactly what the programmer intended.

Is unspecified behavior undefined behavior?

Unspecified behavior is different from undefined behavior. The latter is typically a result of an erroneous program construct or data, and no requirements are placed on the translation or execution of such constructs.

Is printf undefined behavior?

printf("%f\n",0); Above line of code is undefined behavior.

Is an infinite loop undefined behavior?

No thread of execution can execute forever without performing any of these observable behaviors. Note that it means that a program with endless recursion or endless loop (whether implemented as a for-statement or by looping goto or otherwise) has undefined behavior.


2 Answers

However I suspect this is undefined behaviour since it can be both (++*ptr)++ or ++(*ptr++). Is it?

Not really, unlike the runtime behavior, which gives ample leeway to implementors, in C++ parsing itself follows quite strict and well-defined rules1. Indeed, looking at the precedence rules, ++*Ptr++ is actually parsed as ++(*(Ptr++)).

This trick question instead is probably alluding to the undefined behavior of expressions such as i = ++i + ++i, where you have a value that appears multiple times in an expression, and is subjected to a modification by a side-effect of the expression itself. Such expressions are illegal, as, unless there's some operator that sequences the side effects2, the exact moment in which they are applied is not defined, so it's undefined exactly what values i would assume in the various points of the expression.

Still, there's no undefined behavior here, as all side effects in the expression operate on different values, which appear only once in the expression: the "inner" ++ affects Ptr, while the outer one affects the value pointed originally by Ptr, i.e. Ar[0].

++(*(Ptr++))      ^^^^^____increments Ptr, returning its original value    ^^^^^^^^______dereferences the original Ptr, AKA &Ar[0] ^^^^^^^^^^^^_______ increments Ar[0] 

That being said, if I ever saw such an expression in a code base of ours I'd go to great lengths to find the author and make sure that this wouldn't happen again.


  1. If sometimes very bizarre and absurdly costly to implement. Still, there are instances of undefined behavior in the standard describing some corner cases of the parsing, but it's orders of magnitude less pervasive than "runtime" undefined behavior.
  2. A handy summary of those rules can be found here; interestingly, some extra guarantees have been added in C++17.
like image 68
Matteo Italia Avatar answered Sep 19 '22 13:09

Matteo Italia


This

++*Ptr++; 

doesn't cause U.B and is evaluated as ++(*(Ptr++))

  • ptr++; /* address post incremented i.e doesn't change here itself */
  • *ptr; /* dereference same address i.e value at location where ptr earlier pointed i.e 6 */
  • ++*ptr; /* value changed where ptr pointed i.e Ar[0] becomes 7 */

Note that post increments Ptr++ evaluated as

  • Ptr; /* Ptr doesn't change here itself in same expression */
  • Ptr = Ptr + 1; /* in next expression, Ptr considers the incremented one */
like image 23
Achal Avatar answered Sep 19 '22 13:09

Achal