2

Possible Duplicate:
Undefined Behavior and Sequence Points

I am using microsoft visual c++. Look at the following example:

int n = 5;
char *str = new char[32];
strcpy(str, "hello world");
memcpy(&str[n], &str[n+1], 6+n--);
printf(str);
// output is "hell world"

So unexpectadly my compiler produces code that first decrements n and then executes memcpy. The following source will do what i expected to happen:

int n = 5;
char *str = new char[32];
strcpy(str, "hello world");
memcpy(&str[n], &str[n+1], 6+n);
n--;
printf(str);
// output is "helloworld"

First I tried to explain it to myself. The last parameter gets pushed on the stack first, so it may be evaluated first. But I really believe that post increment/decrement guarantee to be evaluated after the next semicolon.

So I ran the following test:

void foo(int first, int second) {
    printf("first: %i / second: %i", first, second);
}
int n = 10;
foo(n, n--);

This will output "first: 10 / second: 10".

So my question is: Is there any defined behaviour to this situation? Can somebody point me to a document where this is described? Have I found a compiler bug ~~O.O~~?

The example is simplyfied to not make sence anymore, it just demonstrates my problem and works by itself.

Community
  • 1
  • 1
typ1232
  • 5,535
  • 6
  • 35
  • 51
  • Is there any defined behaviour => no – ipc Feb 04 '13 at 21:10
  • @ipc: This is puzzling me every time: why is the behavior "undefined" rather than just "unspecified"? Isn't just the order of evaluation of the arguments which is unspecified? – Andy Prowl Feb 04 '13 at 21:12
  • http://stackoverflow.com/questions/376278/parameter-evaluation-order-before-a-function-calling-in-c – chris Feb 04 '13 at 21:13
  • @AndyProwl the order of evaluation is unspecified, accessing the same variable and modifying it in an unsequenced fashion is undefined. Oh wait, I think I misread your question... – Seth Carnegie Feb 04 '13 at 21:13
  • @SethCarnegie: Right, I found that out. For a scalar that's indeed so (*"If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined"*). But if it wasn't a scalar, that would not be undefined behavior, right? – Andy Prowl Feb 04 '13 at 21:15
  • 1
    @AndyProwl I think it's still undefined behaviour, but I don't have a standard reference, let me find it. – Seth Carnegie Feb 04 '13 at 21:17
  • @SethCarnegie: That's indeed what I should deduce from (unexplained) answers given by other people, but I can't find a reference in the standard. – Andy Prowl Feb 04 '13 at 21:19
  • @AndyProwl: Can you think of a side effect not involving scalars? (ok, writing to and reading from a file, but then only the order is unspecified). Note that I didn't use the word "undefined" in my comment. – ipc Feb 04 '13 at 21:22
  • @ipc: I've been told that this is UB even if the operand of `++` is a class object for which `++` has been overloaded. I do not understand why that's true though and I would like to find out. – Andy Prowl Feb 04 '13 at 21:25
  • @ipc: Yes, I've noticed you haven't used the word "undefined", but I thought you meant to imply it (and it is indeed correct in this case). – Andy Prowl Feb 04 '13 at 21:26
  • @AndyProwl: If the ++ operator is overloaded and it does nothing, why should there be UB? If it does something (i.e. modifying a scalar) it becomes UB because "a side effect on a scalar object is unsequenced ..." – ipc Feb 04 '13 at 21:29
  • @ipc: let me complete the sentence: "...relative to either another side effect on the **same** scalar object or a value computation using the value of the **same** scalar object". So the ++ operator could do something (e.g. increment an iterator) and yet this should yield no UB. Or am I missing something? – Andy Prowl Feb 04 '13 at 21:32
  • `f(n, n++)` for example is indeed well defined if `operator++` only increments an iterator that is not read when evaluating or converting `n`. – ipc Feb 04 '13 at 21:36
  • @ipc: Well, that's what I thought. But when I wrote something similar, I was told I was wrong by reliable sources - who unfortunately did not care to explain any further. – Andy Prowl Feb 04 '13 at 21:39

1 Answers1

7

There are two related issues at play. First, the order of execution of function arguments is unspecified. What is guaranteed is that all are executed before entering the body of the function. Second, it is undefined behaviour because you are changing and reading n without any sequence points between those expressions.

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • Thank you. I knew about the unspecified order of execution on arguments, but didn't know this affected the post operators. I thought they would always be executed after the next semicolon. – typ1232 Feb 04 '13 at 21:27