0

Are struct well defined in strict c 89? I mean this code

struct a {
    int a, b;
    void * c;
} k;
//init k...
struct b {
    int u, w;
    long *data;
} p = *(struct b*)&k;

is going to work on every compiler that support the standard? If I reverse the cast (e.g. cast from struct b to struct a) c is going to be the same as the beginning? I'm pretty sure it works with gcc(even with -ansi -pedantic), microsoft compiler and so on, but does it guarantee that it is standard c 89?

Thank you!

krock
  • 28,904
  • 13
  • 79
  • 85
marco6
  • 352
  • 2
  • 12
  • 1
    Sanity aside, there is no assurance that the `void*` value in `k.c` is an address properly aligned to hold an implementation-supported `long` value. Which is to say, unless the address in `k.c` is from a known-validly-aligned address-of-long (or something more strict on the implementation), you run the risk of a bus-error on dereference of `p.data`. – WhozCraig Dec 05 '12 at 10:33
  • yeah, I know that k.c is a valid address of long, ad that I'm going to convert just from long* to void* and viceversa! – marco6 Dec 05 '12 at 10:44
  • @WhozCraig: Even beyond is issue of alignment, is there any guarantee that the bit representation of a `void*` and a `sizeof(long*)` will match (or even be the same size)? Not all machines support hardware byte addressing; on some DSPs, for example, a pointer is 16 bits and points to a 16-bit word of memory. The compiler I used for one of those implemented `char` and `int` as 16 bits, but unless later standards have changed, it could legally have had `char` be 8 bits, `sizeof(int*)` be 2 (one 16-bit word) and `sizeof(void*)` be 4 (two 16-bit words). That would have significantly... – supercat Dec 05 '12 at 15:59
  • ...slowed down operations with `char*` types (good reason for the compiler not to do that) but I think some later DSPs in that family added some instructions to load or store a char accessed as base[index], where `base` is a word address and `index` is a byte offset; if compilers for those DSPs offer an 8-bit `char` option, the logical size for `char*` would be two 16-bit words while `int*` would be one. – supercat Dec 05 '12 at 16:03

1 Answers1

4

Don't do this. Copy the fields manually:

struct b p;

p.u = k.a;
p.w = k.b;
p.data = (long *) k.c;

Your code would most likely run just fine since long * and void * will typically be identically implemented, but why risk it? The standard says stuff like:

A pointer to void shall have the same representation and alignment requirements as a pointer to a character type.39) Similarly, pointers to qualified or unqualified versions of compatible types shall have the same representation and alignment requirements. All pointers to structure types shall have the same representation and alignment requirements as each other. All pointers to union types shall have the same representation and alignment requirements as each other. Pointers to other types need not have the same representation or alignment requirements.

Note the last sentence, where pointers to "other types" (such as long) are made distinct from pointers to void.

The above is explicit, safe, and much clearer.

unwind
  • 391,730
  • 64
  • 469
  • 606
  • 2
    There is (void *)vs(long *) NOT (void *)vs(long). – jacekmigacz Dec 05 '12 at 10:25
  • how long* and void* can be different sized? Aren't they just pointers? I remember my teacher explaining that the type of a pointer is just used at compile time.. Is he wrong? – marco6 Dec 05 '12 at 10:40
  • @user1878593 Your teacher is right for a class of platforms, but wrong if the statement is meant to encompass all platforms supported by the C standard. See [this question](http://stackoverflow.com/questions/916051/are-there-are-any-platforms-where-pointers-to-different-types-have-different-siz) for details. – user4815162342 Dec 05 '12 at 10:46
  • Independently of this, `void *` is guaranteed to be large enough to hold any *data* pointer, so that a data pointer survives a round-trip to `void *` and back. – user4815162342 Dec 05 '12 at 10:46
  • @jacekmigacz Thanks, I mis-read the question. I've edited the answer. – unwind Dec 05 '12 at 11:36