There is a well known pattern of figuring out array length:
int arr[10];
size_t len = sizeof(arr) / sizeof(arr[0]);
assert(len == 10);
This pattern applies to static arrays and auto arrays of constant size. It also applies to variable length arrays in C99.
I want to apply similar idea for figuring out dynamic array size in bytes:
size_t known_len = 10;
int *ptr = malloc(known_len * sizeof(int));
size_t size = known_len * sizeof(ptr[0]);
assert(size == known_len * sizeof(int));
This is nicer than known_len * sizeof(int)
because sizeof(ptr[0])
doesn't refer to actual array element type. Hence it doesn't require reader of the code to know the type.
However it is unclear to me whether expression sizeof(ptr[0])
can lead to undefined behavior. As it is expanded:
sizeof(ptr[0]) -> sizeof(*((ptr) + (0))) -> sizeof(*ptr)
The result expression is questionable in case if ptr
is 0
:
sizeof(*((int*) 0))
According to a C99 standard:
(C99, 6.3.2.3p3 ): "An integer constant expression with the value
0
, or such an expression cast to typevoid *
, is called a null pointer constant." Dereferencing a null pointer is undefined behavior.(C99, 6.5.3.2.p4) "If an invalid value has been assigned to the pointer, the behavior of the unary
*
operator is undefined.87)"87): "Among the invalid values for dereferencing a pointer by the unary
*
operator are a null pointer, an address inappropriately aligned for the type of object pointed to, and the address of an object after the end of its lifetime."
But it's never specified whether sizeof of such expression can lead to undefined behavior. In fact such sizeof should be evaluated at compile time.
My questions are:
- Can the expression
sizeof(ptr[0])
be used in the code when type ofptr
is known and the value ofptr
is not known? - Can such use be justified according to C99 standard? GNU GCC spec?
In general case, if I'm missing something, dereferencing a null pointer under
sizeof
can lead to undefined behavior. Since C99,sizeof
is not a purely compile time construct. The operand ofsizeof
is evaluated at run-time if the operand type is a VLA.Consider the following example
According to the C99 standard, the argument of
sizeof
is supposed to be evaluated (i.e.i
is supposed to get incremented). Yet I'm not entirely sure that the null-point dereference ina[0]
is supposed to produce undefined behavior here.