Reputation: 2003
I wrote the following as part of an answer to a question about sizeof
, and its behavior with regard to C99 VLAs:
It would not be difficult to intentionally create a case where the semantics of
count_of
would effectively differ for a VLA but it might be difficult to create a readable, easily understandable/maintainable, and useful case (I haven't tried to).
After thinking about this, I'm not sure if this statement is actually true. To create a VLA in the first place, the compiler must first determine the amount of space the VLA will require.
For sizeof
, we know that
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. (6.5.3.4/2)
and although VLA size is obviously a run-time determination, after evaluation (if any, including any side effects) of the size expression for the VLA declarator:
The size of each instance of a variable length array type does not change during its lifetime. Where a size expression is part of the operand of a sizeof operator and changing the value of the size expression would not affect the result of the operator, it is unspecified whether or not the size expression is evaluated. (6.7.5.2/2)
So, given
#define count_of(arr) (sizeof(arr)/sizeof(arr[0]))
is there any case where the actual effective behavior of a macro such as this could differ for a VLA vs. an array declaration where the array-size expression is a constant expression (i.e. a plain-old pre-C99 fixed-size array)?
Upvotes: 7
Views: 750
Reputation:
The obvious answer is when arr
is an expression containing a side effect. If sizeof
's argument is evaluated, the side effect takes place. If it isn't evaluated, there is no side effect.
#include <stdio.h>
#define LENGTHOF(arr) (sizeof(arr) / sizeof(*(arr)))
void f() {
puts("f");
}
int main() {
const int n = 4;
int array[n];
return LENGTHOF(*(f(), &array)) - 4;
}
This is valid in C99, where array
is a VLA, and in C++, where n
is a constant expression and array
is not a VLA. In C99, this prints f
. In C++, this does not print anything.
Upvotes: 6