Search code examples
cpointersinitializationdeclarationsizeof

Why can I use a pointer while it's being defined elsewhere at the same time?


Let's assume I have a struct like this:

typedef struct {
    char* author;
    uint32_t isbn;
} Book;

int
main( int arg_c; char* arg_v[] ) {
    Book* b = malloc( sizeof *b );
    char* author = "Miller";

    //[...]

    free(b);
    return 0;
}

Now what kinda trips me up is line 8: Book* b = malloc( sizeof *b ); here, I'm creating a pointer b of type Book on the left side of the equals sign, but at the same time, I'm dereferencing b on the right side to allocate memory for b.

How does that work?

How can I define a pointer at the same time, as I use that pointer to allocate memory for it. If they line were Book* b = malloc( sizeof (Book) ); that is immediately intuitive for me, since sizeof interrogates the size of a type. But here, it's as if the identifier is used in two places at the same time, while it's being defined.

Is there some double-pass thing going on, that I'm missing?


Solution

  • This expression

    sizeof *b
    

    is not evaluated. The compiler just tries to determine the type of the expression *b and this type is Book. So in fact this expression is equivalent to

    sizeof( Book )
    

    The type of the variable b is known after completion of the definition of its declarator. So the initializer expression already knows the type of the initialized object.

    To make it more clear consider the following demonstrative program

    #include <stdio.h>
    
    int main(void) 
    {
        int x = 10;
        
        size_t n = sizeof( x += 20 );
        
        printf( "n = %zu, x = %d\n", n, x );
        
        return 0;
    }
    

    The program output is

    n = 4, x = 10
    

    As this expression

    sizeof( x += 20 )
    

    is not evaluated (the compiler only determines the type of the expression) then the value of the variable x was not changed.

    Another more complicated example.

    #include <stdio.h>
    
    int i = 1;
    
    int main(void) 
    {
        size_t i[i], b = sizeof( i );
    
        printf( "b = %zu\n", b );
    
        return 0;
    }
    

    The program output is

    b = 8
    

    Within the declaration of the array i there is used the variable i declared in the file scope because the declarator of the array i is not completed yet. But in the declaration of the variable b there is used the identifier i that denotes the array.