views:

112

answers:

2

Suppose this code:

unsigned char list[3] = { 1, 2, 3 };
struct _struct{
  unsigned char a;
  unsigned char b;
  unsigned char c;
} *s;
s = ( _struct * ) list; 

Can I assume that always s->a == 1, s->b == 2, s->c == 3 ?
Or it will depend on the system's endianness or memory alignment?

+4  A: 

Yes, it will depend on the system's and compiler's memory alignment and packing rules.

Oli Charlesworth
Is that yes he can assume it's as his example, or yes it depends on the machine architecture?
Gary Willoughby
"Yes, it will depend on the system..."
Oli Charlesworth
I thought endianness only effects types over 1 byte and as this is a structure and no unions or larger types are being used, i would of though this would be safe?
Gary Willoughby
I agree that endianness probably doesn't come into it. However, compiler packing rules do, and these in turn will be affected by the architecture's alignment constraints. Also, I think the compiler is free to place struct members in any order (not sure if this is true).
Oli Charlesworth
I suspected more of alignment than of endianness, just threw them all together to be more comprehensive
Petruza
+1  A: 

Let's dissect this.

In all cases, sizeof(char) == 1, and the list array will have its three members at memory locations list, list + 1, and list + 2.

The situation with the struct is not quite as clear. The Standard guarantees that the members will be allocated in increasing memory locations, but not that they will be contiguous. The compiler is free to introduce padding between members, and padding at the end.

Therefore, s->a == 1 will always be true. If the implementation puts the unsigned chars in the struct adjacent (and most will), then the other equalities will necessarily be true.

By the way, calling a struct _struct may cause problems. A name beginning with an underscore in the global namespace is reserved for the implementation.

David Thornley