[cfe-dev] sizeof(sizeof(...))

Ted Kremenek kremenek at apple.com
Fri Dec 14 15:02:28 PST 2007

On Dec 14, 2007, at 2:48 PM, Oliver Hunt wrote:

>> The sizeof operator yields the size (in bytes) of its operand,  
>> which may be an
>> expression or the parenthesized name of a type. The size is  
>> determined from the type of
>> the operand. The result is an integer. If the type of the operand  
>> is a variable length array
>> type, the operand is evaluated; otherwise, the operand is not  
>> evaluated and the result is an
>> integer constant.
> Egad, so a = sizeof(char[(int)sqrt(x)]); would be valid?  that  
> scares me :-O

Yes this is valid.  It scares me too.

> is this valid:
> char[n*m] foo(int n, int m) { ... }
> ...
> a=sizeof(foo(x,y))
> ?

This (I believe) is not valid, and I couldn't get gcc to compile  
similar code.  From the standard: "All declarations of variably  
modified (VM) types have to be either block scope or function  
prototype scope."  I believe the function prototype scope only  
encompasses the parameters of the function and not the return type.

Here is some more stuff from the standard on the topic:

0 EXAMPLE 4 All declarations of variably modified (VM) types have to  
be at either block scope or function prototype scope. Array objects  
declared with the static or externstorage-class specifier cannot have  
a variable length array (VLA) type. However, an object declared with  
the static storage- class specifier can have a VMtype (that is, a  
pointer to a VLA type). Finally, all identifiers declared with a VM  
type have to be ordinary identifiers and cannot, therefore, be members  
of structures or unions.

extern int n;
int A[n]; //invalid: file scope VLA
extern int (*p2)[n]; //invalid: file scope VM
int B[100]; //valid: file scope but not VM

void fvla(int m, int C[m][m]); //valid: VLA with prototype scope

void fvla(int m, int C[m][m]) //valid: adjusted to auto pointer to VLA
   typedef int VLA[m][m]; //valid: blockscope typedef VLA
   struct tag {
     int (*y)[n]; //invalid:ynot ordinary identifier
     int z[n]; //invalid:znot ordinary identifier

   int D[m]; //valid: auto VLA

   static int E[m]; //invalid: static blockscope VLA

   extern int F[m]; //invalid: F has linkage and is VLA

   int (*s)[m]; //valid: auto pointer to VLA

   extern int (*r)[m]; //invalid:rhas linkage and points to VLA

   static int (*q)[m] = &B; //valid:qis a static blockpointer to VLA

More information about the cfe-dev mailing list