Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When is it legal to type-pun using a pointer-to-a-pointer in C?

In a C program I have a struct

typedef struct {
    void *payload; // opaque, real type known to callbacks

         ... some stuff ...
} MiddleMan;

To create some veneer of type-safety I might create getters and setters

CbData *get_cb_data(const MiddleMan *mm){ return mm->payload; }   
void set_cb_data(MiddleMan *mm, CbData *cbd){ mm->payload = cbd; }

Or I can try to do it with a single, pointer-based accessor

CbData **cb_data(MiddleMan *mm){return (CbData**)&mm->payload;}

Now the second solutions looks dodgier than the first, and it also restricts users to non-const mm even if they only want to read. But my question is whether it is even legal C?

I'm fairly sure you can get away with it on any architecture where void* is the same size & format as CbData*. But can anyone give clear reasoning why this is (or is not) valid in general?

like image 324
Adrian Ratnapala Avatar asked Sep 05 '13 13:09

Adrian Ratnapala


People also ask

Why pointer to reference is not allowed?

You can have a pointer to an object (or function), but you can't have a pointer to an object's name. For this very reason, the idea of a pointer to a reference makes no sense. In other words, references are immaterial, in general case they simply do not exist in memory.

Is type punning undefined behavior?

Most of the time, type punning won't cause any problems. It is considered undefined behavior by the C standard but will usually do the work you expect. That is unless you're trying to squeeze more performance out of your code through optimizations.


1 Answers

Generally, you shouldn't do that. A void** may have the different alignment requirement with CbData**. An explicit cast may produce the different address.

C standard 6.2.5.27:

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.

like image 178
Eric Z Avatar answered Sep 28 '22 01:09

Eric Z