Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the operand of `sizeof` evaluated with a VLA?

Tags:

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?

like image 911
PC Luddite Avatar asked Oct 07 '15 06:10

PC Luddite


People also ask

What is sizeof () operator in pointer?

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.

How does sizeof know array size?

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.

How does sizeof work?

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.

Does sizeof return array size?

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.


1 Answers

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.

like image 70
M.M Avatar answered Oct 14 '22 00:10

M.M