Sometimes I do pointer arithmetic on structures and I'm not certain if it's defined behavior or not..
If I have this structure
typedef struct SCustomData{
uint32_t a;
uint32_t b;
}CustomData;
Rather than having to constantly type out different fields of the structure sometimes to me it makes sense to just give it a constant size and fit whatever I need to in there.
My first question is: Is it defined behavior that the address of the structure is also the address of the first variable in the structure?
int main(){
CustomData cd = {0};
cd.a = 0xDEADBEEF;
uint32_t a = 0;
memcpy(&a,&cd,sizeof(uint32_t));
assert(a==0xDEADBEEF);
return 0;
}
Will that always succeed?
My next question is, can I use pointer arithmetic to access any member of the structure so long as I know the sizes of each member?
int main(){
CustomData cd = {0};
cd.b = 0xABCD0000;
uint16_t highshort = *(uint16_t*)((uint8_t*)&cd sizeof(uint32_t) sizeof(uint16_t));
assert(highshort == 0xABCD);
uint8_t highbyte = *(uint8_t*)((uint8_t*)&cd sizeof(uint32_t) sizeof(uint16_t) sizeof(uint8_t));
assert(highbyte == 0xAB);
return 0;
}
Aside from maybe looking ugly or bad code practice, is at least defined behavior? Should I avoid it?
And if I didn't use pointer casting and used memcpy instead is it still a bad idea?
int main(){
CustomData cd = {0};
cd.b = 0xABCD0000;
uint16_t highshort = 0;
memcpy(&highshort, ((uint8_t*)&cd) sizeof(uint32_t) sizeof(uint16_t), sizeof(uint16_t));
assert(highshort == 0xABCD);
return 0;
}
CodePudding user response:
First Question
It's actually is defined in the C standard! Section 6.7.2.1
(in this standard draft)
15 Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared. A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa. There may be unnamed padding within a structure object, but not at its beginning.
Second Question
It's not defined according to the standard (again section 6.7.2.1
):
Each non-bit-field member of a structure or union object is aligned in an implementation- defined manner appropriate to its type.
However, most compilers align the same way (per-architecture and bitness at least)
Why It's still a bad idea
Maintainability - Your code will be much easier to maintain if you use the members themselves. It won't be dependent on the compiler and bitness, and won't be sensitive to changes in your code (such as changing types or reordering members).
Readability - Your intentions will of course be much clearer.