There are a few problems, the warning you are seeing is due the unspecified order of evaluation of the argument to your function. The C99 draft standard section 6.5.2.2
Function calls paragraph 10 says:
The order of evaluation of the function designator, the actual arguments, and subexpressions within the actual arguments is unspecified, but there is a sequence point before the actual call.
you are also modifying a variable more than once within a sequence point which is undefined behavior and can not be relied on to work, section 6.5
Expressions paragraph 2 says (emphasis mine going forward):
Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression.72) Furthermore, the prior value shall be read only to determine the value to be stored.73)
Also, note that the standard allows for padding between elements of a struct but beyond that scalar is considered an array of one element and so incrementing beyond the array and then performing indirection would be undefined as well. This is covered in section 6.5.6
Additive operators paragraph 7:
For the purposes of these operators, a pointer to an object that is not an element of an array behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type.
and going more than one past the array bounds of accessing one past the array bounds is undefined by section 6.5.6
Additive operators paragraph 8:
[...]If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined. If the result points one past the last element of the array object, it shall not be used as the operand of a unary * operator that is evaluated.
We can see depending on the optimization level gcc
will output (see it live):
3 3 2
or (see it live):
3 3 3
neither of which is the desired output.
The standards compliant way to access your structs members via a pointer would be to use offsetof and here, which requires including stddef.h
. Accessing member a
would look like this:
*( (int*) ((char*)aBadBoyPointer+offsetof(myStruct, a)) )
^ ^ ^
3 2 1
There are three elements here:
- Use
offsetof
to determine the offset in bytes of the member - Cast to *char ** since we need pointer arithmetic in bytes
- Cast back to *int ** since that is the correct type