typedef VLA 是否需要计算大小表达式?
int f(void);
int main(void)
{
typedef int (T) [ f() ]; // is f required to be evaluated ?
T x;
return sizeof x;
}
typedef 指向 VLA 的指针是否需要计算大小表达式?
int f(void);
int main(void)
{
typedef int (*T) [ f() ]; // is f required to be evaluated ?
T x;
return sizeof x;
}
UPD。在
f
的定义中是可见的,那么对它的调用可能会被优化掉:
int f(void)
{
return 4;
}
int main(void)
{
typedef int (*T) [ f() ];
return sizeof(T);
}
生成的代码(GCC 和 LLVM):
main:
mov eax, 8
ret
这是预期的,因为没有真正需要调用
f
来确定指针的大小。
根据 C 标准(§6.7.8 类型定义)
3 在存储类说明符为 typedef 的声明中,每个 声明符将标识符定义为 typedef 名称,表示 按照 6.7.6 中描述的方式为标识符指定类型。 任意 与可变长度数组关联的数组大小表达式 每次声明 typedef 时都会评估声明符 name 按照执行顺序到达。
C 标准中有一个例子
8 示例 5 如果 typedef 名称表示可变长度数组类型, 数组的长度在 typedef 名称是固定的 定义,而不是每次使用时:
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];
}
这是一个演示程序。
#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();
}
}
程序输出为
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