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);
T
As an expression (not a declaration), ptr[0]
is identical to *ptr
.
As long as the type of ptr
is known and it is not pointing to void, sizeof
is guaranteed to work on sizeof(*ptr)
as well as sizeof(ptr[0])
.
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 of sizeof
is evaluated at run-time if the operand type is a VLA.
Consider the following example
unsigned n = 10;
int (*a)[n] = NULL; // `a` is a pointer to a VLA
unsigned i = 0;
sizeof a[i++]; // applying `sizeof` to a VLA
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 in a[0]
is supposed to produce undefined behavior here.
The code is evil.
size_t known_len = 10;
int *ptr = malloc(known_len);
size_t size = known_len * sizeof(ptr[0]);
assert(size == known_len * sizeof(int));
The size of the memory allocation from your view point is 10 bytes. That is not 10 pointers to int.
known_len / sizeof(ptr[0])
will give you the number of integers that the allocation can hold.
As is, you are likely to go off the end of the allocation, leading to undefined behavior.
Consider malloc(known_length * sizeof ptr[0]);
The expression ptr[0]
will not be evaluated in sizeof(ptr[0])
. Size will be determined by just using the type of ptr[0]
at compile time.
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 aninteger constant.
That means, there is no undefined behavior.
This will not cause undefined behavior.
With the exception of taking the size of variable-length arrays, sizeof
is a compile-time constant expression. The compiler processes the expression to determine its type, without producing the code to evaluate the expression at compile time. Therefore, the value at ptr[0]
(which is an uninitialized pointer) does not matter at all.
Moreover, if you would like to allocate ten integers, you should be calling malloc
like this:
int *ptr = malloc(known_len * sizeof(ptr[0]));
Otherwise, you allocate ten bytes, which is too small for storing ten integers. Note that in the expression above ptr
is uninitialized at the time of the call, which is perfectly fine for sizeof
.