Petr Skocik
Petr Skocik

Reputation: 60067

Generic write to a struct pointer

6.2.5p28:

A pointer to void shall have the same representation and alignment requirements as a pointer to a character type.48) 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.

Does this mean I can generically write to a struct pointer as in:

struct a_struct;

int 
alloc_struct(struct a_struct **X, size_t Sz)
{
    if ((*X=malloc(Sz))) 
        return 0;
    return -ENOMEM;
}

struct foo{ int x; char buf[32]; };;

int main()
{
    struct foo *foo_p;
    alloc_struct((struct a_struct**)&foo_p, sizeof(*foo_p));
}

Upvotes: 0

Views: 925

Answers (2)

supercat
supercat

Reputation: 81189

Because the costs of supporting various kinds of aliasing can vary significantly among platforms (aliasing between floats and integers being particularly expensive), and because different kinds of application have varying needs for aliasing, the authors of the C89 Standard made no effort to describe all of the forms that should be supported by implementations targeting any particular platform or application field. Existing implementations were already supporting aliasing in cases where it was useful, and the authors of the Standard had no reason to expect them to stop.

There is no reason why a quality implementation should be unable to support constructs such as the one you describe, especially in cases where a compiler would be able to see a cast to struct a_struct** within a function call and the target of pointer is accessed only via struct a_struct**, but some implementers view the Standard's failure to mandate support for such constructs as implying a judgment that there was no benefit to supporting such constructs.

Consequently, there are two ways to achieve the semantics you seek: (1) manipulate pointers by reading and writing individual characters thereof (there are some cases where the Effective Type would make memcpy/memmove unsafe), or (2) disable type-based aliasing, and add restrict qualifiers where appropriate to make the code more efficient than it would have been with type-based aliasing enabled.

Upvotes: 3

2501
2501

Reputation: 25753

No, you're still violating strict aliasing.

Types struct a_struct* and struct foo* are not compatible and they are not on the list of exceptions to this rule.

This is no different that alising an int as a float:

int a;
int* b = a;
float* c = ( float* )b;
*c = 1.0f;

or aliasing an int* as a float*, which is what your example does, except they are struct pointers:

int* a;
int** b = &a;
float** c = ( float** )b;
*c = NULL;

Even if both pointers have the same alignment and representations the types cannot alias as they are not compatible.

Upvotes: 2

Related Questions