An argument in the comments section of this answer prompted me to ask this question.
In the following code, bar
points to a variable length array, so the sizeof
is determined at runtime instead of compile time.
int foo = 100; double (*bar)[foo];
The argument was about whether or not using sizeof
evaluates its operand when the operand is a variable length array, making sizeof(*bar)
undefined behavior when bar
is not initialized.
Is it undefined behavior to use sizeof(*bar)
because I'm dereferencing an uninitialized pointer? Is the operand of sizeof
actually evaluated when the type is a variable length array, or does it just determine its type (how sizeof
usually works)?
Edit: Everyone seems to be quoting this passage from the C11 draft. Does anyone know if this is the wording in the official standard?
The sizeof operator gives the amount of storage, in bytes, required to store an object of the type of the operand. This operator allows you to avoid specifying machine-dependent data sizes in your programs.
sizeof(type) gives you the number of bytes of the type you pass. Now if you pass array then the compiler knows that this is an array and number of elements in it and it just multiplies that many elements with the respective data-type size value. Again the sizeof(int) or sizeof(pointer) is platform dependent.
It is a compile-time unary operator and used to compute the size of its operand. It returns the size of a variable. It can be applied to any data type, float type, pointer type variables. When sizeof() is used with the data types, it simply returns the amount of memory allocated to that data type.
The sizeof() operator returns pointer size instead of array size. The 'sizeof' operator returns size of a pointer, not of an array, when the array was passed by value to a function.
Yes, this causes undefined behaviour.
In N1570 6.5.3.4/2 we have:
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.
Now we have the question: is the type of *bar
a variable length array type?
Since bar
is declared as pointer to VLA, dereferencing it should yield a VLA. (But I do not see concrete text specifying whether or not it does).
Note: Further discussion could be had here, perhaps it could be argued that *bar
has type double[100]
which is not a VLA.
Supposing we agree that the type of *bar
is actually a VLA type, then in sizeof *bar
, the expression *bar
is evaluated.
bar
is indeterminate at this point. Now looking at 6.3.2.1/1:
if an lvalue does not designate an object when it is evaluated, the behavior is undefined
Since bar
does not point to an object (by virtue of being indeterminate), evaluating *bar
causes undefined behaviour.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With