Help me please understand the following expression:

(seen in a book)

*((int *)marks + i++) = i+1

A large number of increments and symbols dereference confusing!

有帮助吗?

解决方案 6

(int *)marks

cast marks to a int pointer

+ i++

add i at marks (chaging the address pointed) and then increments i by 1

*(...) = i+1

set the VALUE of the cell pointed by our pointer to i+1 (pay attention at the fact that i as already been incremented before, so it will be greater of 2 by the start of the instruction.

I hope this is an example f how you should NOT write the code :)

其他提示

I hope the book had this as a bad example, because the behavior of that is undefined.

(int *)marks interprets marks (whatever that may be) as a pointer to int, then we have the result of i++ added to that. This pointer is dereferenced and i+1 is assigned to the corresponding object.

This expression has no defined behavior because it reads and modifies i at two different subexpressions that are not sequenced one before the other.

Burn the book.

The behaviour of the statement is undefined due to there being no sequence points. A far simpler case to understand is i++ = i which is also undefined.

Note: As others have said, the i++ expression is undefined behavior. In g++, the i++ operation will be executed as follows:

// Pointer to some data.
void* marks = ???;
// Typecast to an integer pointer
int* marksIntPointer = (int*)marks;
// Move the position in memory. I am assuming that 'marks' is an array.
int* marksIntPointerOffset = marksIntPointer + i;
// Undefined behaviour, could take place here or before, depending on the compiler (as others have said).
i++;
// Set the value of the desired memory.
*marksIntPointerOffset = i+1;

The mentioned expression yields an undefined behavior.

C99 6.5 §2 states:

1) Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression.

2) Furthermore, the prior value shall be read only to determine the value to be stored.


1) Storing and modifying the value of variable within a single expression is pretty straightforward:

i = ++i;
i++ = i;
++i = 7;

as well as modifying the value of the same variable multiple times within a single expression:

j = ++i + ++i;

2) Reading only to determine the value to be stored might be a bit tricky though. This means that even the following (just like the previous examples) invoke the undefined behavior:

j = (i + 1) + i++;
a[i++] = i;  
*(ptr + i++) = i;

as well as:

*((int *)marks + i++) = i+1

You might look at: Undefined behavior and sequence points as well :)

As others have mentioned, the behavior is undefined; by getting rid of the ++ operator, the following code would be well-defined (but still ugly as sin):

*((int *)marks + i) = i+1

Here's how it breaks down:

         marks               -- take the expression marks
  (int *)marks               -- cast it as a pointer to int
  (int *)marks + i           -- offset i integer elements from that address
*((int *)marks + i)          -- deference the result to get an array element
*((int *)marks + i) = i+1    -- assign the result of i+1 to that element

This is essentially treating marks as an array of int, and assigning the result of i+1 to the i'th element:

int *mp = (int *) marks;
mp[i] = i+1

The original expression was trying to do

mp[i++] = i+1

which invokes undefined behavior. Since the order in which i++ and i+1 are evaluated is not specified; the compiler is free to evaluate them in any order it feels like. Since i++ has a side effect (updating the value of i), this means that you will get different results based on the platform, optimization settings, even the surrounding code. The language standard explicitly leaves the behavior undefined so that the compiler isn't required to handle this code in any particular way. You will get a result, but it's not guaranteed to be consistent from compiler to compiler (or even from run to run).

Let's see.

*((int *)marks + i++) = i+1

-marks is cast to a pointer to int
-i is incremented by one
-the pointer (int *)marks is advanced by the value (i+1) using pointer arithmetic
-this pointer is now dereferenced, so...
-... the memory location to which it points is now written with the value of i+1

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top