pmor
pmor

Reputation: 6286

Does typedef (pointer to) VLA require evaluation of the size expression?

Does typedef VLA require evaluation of the size expression?

int f(void);
int main(void)
{
    typedef int (T) [ f() ];       // is f required to be evaluated ?
    T x;
    return sizeof x;
}

Does typedef pointer to VLA require evaluation of the size expression?

int f(void);
int main(void)
{
    typedef int (*T) [ f() ];      // is f required to be evaluated ?
    T x;
    return sizeof x;
}

UPD. In the definition of f is visible, then a call to it may be optimized out:

int f(void)
{
    return 4;
}

int main(void)
{
    typedef int (*T) [ f() ];
    return sizeof(T);
}

Generated code (both GCC and LLVM):

main:
        mov     eax, 8
        ret

It is expected, because there is no real need to call f to determine the size of a pointer.

Upvotes: 4

Views: 215

Answers (1)

Vlad from Moscow
Vlad from Moscow

Reputation: 311068

According to the C Standard (§6.7.8 Type definitions)

3 In a declaration whose storage-class specifier is typedef, each declarator defines an identifier to be a typedef name that denotes the type specified for the identifier in the way described in 6.7.6. Any array size expressions associated with variable length array declarators are evaluated each time the declaration of the typedef name is reached in the order of execution.

And there is an example in the C Standard

8 EXAMPLE 5 If a typedef name denotes a variable length array type, the length of the array is fixed at the time the typedef name is defined, not each time it is used:

void copyt(int n)
{
    typedef int B[n]; // B is n ints, n evaluated now
    n += 1;
    B a; // a is n ints, n without += 1
    int b[n]; // a and b are different sizes
    for (int i = 1; i < n; i++)
        a[i-1] = b[i];
}

Here is a demonstration program.

#include <stdio.h>

int f( void )
{
    static int n;
    
    return ++n;
}

void g( void )
{
    typedef int ( *T )[ f() ];
    
    T p;
    
    printf( "sizeof( *p ) = %zu\n", sizeof( *p ) );
}

int main(void) 
{
    for ( size_t i = 0; i < 10; i++ )
    {
        g();
    }
}

The program output is

sizeof( *p ) = 4
sizeof( *p ) = 8
sizeof( *p ) = 12
sizeof( *p ) = 16
sizeof( *p ) = 20
sizeof( *p ) = 24
sizeof( *p ) = 28
sizeof( *p ) = 32
sizeof( *p ) = 36
sizeof( *p ) = 40

Upvotes: 7

Related Questions