Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do pointers to pointers to structs have implied interchangeability?

According to both C99 §6.2.5p27 and C11 §6.2.5p28:

All pointers to structure types shall have the same representation and alignment requirements to each other.

With a footnote (#39 and #48 respectively):

The same representation and alignment requirements are meant to imply interchangeability as arguments to functions, return values from functions, and members of unions.

(Note that C89 §3.1.2.5 doesn't specify about pointers to structs)

-

It is known that a pointer to void for example, C11 §6.3.2.3p1:

A pointer to void may be converted to or from a pointer to any object type.

Does not imply that a pointer to pointer to void is the same as a pointer to void, and does not imply the same as other pointers to pointers to data objects.

(I apologize if I use the term 'imply the same' too loosely, it is meant to be used only within the specified context)

The following is a code sample demonstrating a generic pointer to pointer to struct:

#include <stdio.h>
#include <stdlib.h>

int allocate_struct(void *p, size_t s) {
    struct generic { char placeholder; };    

    if ( ( *(struct generic **) p = malloc(s) ) == NULL ) {
        fprintf(stderr, "Error: malloc();");
        return -1;
    }

    printf("p:  %p;\n", (void *) *(struct generic **) p);
    return 0;
}

int main(void) {
    struct s1 { unsigned int i;  } *s1;

    if (allocate_struct(&s1, sizeof *s1) != 0)
        return -1;

    printf("s1: %p;\n\n", (void *) s1);

    s1->i = 1;
    free(s1);
    return 0;
}

GCC:

-std=c89 -pedantic-errors -Wall -Wextra -fstrict-aliasing -Wstrict-aliasing=3 -O3

Result: (without warnings)

p:  0x800103a8;
s1: 0x800103a8;

.

The Question

Whether the implied interchangeability of pointers to structs applies to pointers to pointers of structs just as well?

Just to clarify: the question is about struct x ** vs other struct y **, and not about struct x * vs struct y **.

like image 664
Dror K. Avatar asked Jun 06 '14 12:06

Dror K.


1 Answers

The complete text of §6.2.5p28 in C11 already answers you:

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.

To organize the paragraph a bit (define "==" as "have the same representation and alignment requirements"):

  • void * == char *
  • type-qualifier(s) X * == X *
  • struct X * == struct Y *
  • union X * == union Y *

In the end, the paragraph explicitly says:

Pointers to other types need not have the same representation or alignment requirements.

Since struct X * and struct Y * are two separate types, which are neither char, struct or union, then pointers to them do not necessarily have the same representation and alignment requirements. Therefore, struct X ** and struct Y ** are not guaranteed to have the same representation and alignment requirements.

like image 142
Shahbaz Avatar answered Oct 02 '22 23:10

Shahbaz