11

Can you explain how the sizeof() works with a random length array? I thought sizeof() on an array is calculated during the compilation, however, the size of an array with random length seems to be calculated correctly.

Example:

#include <stdlib.h>
#include <stdio.h>
#include <time.h>

int main(){
    srand ( (unsigned)time ( NULL ) );
    int r = rand()%10;
    int arr[r]; //array with random length
    printf("r = %d size = %d\n",r, sizeof(arr)); //print the random number, array size
    return 0;
}

The output from multiple runs:

r = 8 size = 32
r = 6 size = 24
r = 1 size = 4

Compiler: gcc 4.4.3

Graham Borland
  • 60,055
  • 21
  • 138
  • 179
zoli2k
  • 3,388
  • 4
  • 26
  • 36
  • I have no idea how `int arr[r];` compiles. I thought arrays in stack need to have their size known during compilation. – orip Aug 17 '11 at 13:46
  • 3
    @orip: have a look at Variable Length Arrays for C99 – Necrolis Aug 17 '11 at 13:47
  • 1
    Look at this: http://stackoverflow.com/questions/737240/c-c-array-size-at-run-time-w-o-dynamic-allocation-is-allowed – user576796 Aug 17 '11 at 13:52
  • 4
    Note that if `rand()%10` happens to be 0, the behavior is undefined. C doesn't support zero-sized arrays (though gcc may do so as an extension). – Keith Thompson Aug 17 '11 at 14:26

4 Answers4

13

In C99 sizeof variable sized arrays is computed in runtime. From the C99 draft 6.5.3.4/2:

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

Andreas Brinck
  • 51,293
  • 14
  • 84
  • 114
  • can you explain to me more details, I don't understand much regarding this question and your answer. Don't be crazy with me. Please. – vietean Aug 17 '11 at 13:53
  • 1
    The point here is that in C99 the size of arrays doesn't have to be specified at compile time. In this case sizeof isn't being evaluated at compile time but at runtime. – Andreas Brinck Aug 17 '11 at 13:55
  • Does that mean that memory occupation of an array may be the array size plus additional bytes to store its size? – zoli2k Aug 17 '11 at 14:02
  • @zoli2k: No. The size of the array (or more likely the number of elemente) will be stored somewhere in memory, but that's not counted as part of the array size. `sizeof arr` is the number of elements multiplied by the size of each element. – Keith Thompson Aug 17 '11 at 14:18
  • The size might or might not need to be stored depending on how the compiler manages the stack and whether `sizeof` is used. This is an implementation detail. – R.. GitHub STOP HELPING ICE Aug 17 '11 at 14:36
  • 1
    @R..: You're right. The size has to be accessible somehow, but if it's never used it can be optimized away, and if it *can* be computed at compile time (even if it's not a constant expression), then it needn't be stored anywhere even if it's used. The point is that there can be additional data generated by the compiler, possibly occupying memory, but it doesn't count towards `sizeof arr`. – Keith Thompson Aug 17 '11 at 16:07
3

In your code, arr is a special kind of array: it is a VLA (variable length array).

The paragraph for sizeof in the Standard (6.5.3.4) says

If the type of the operand is a variable length array type, the operand is evaluated

so it's not a compile-time constant.

pmg
  • 106,608
  • 13
  • 126
  • 198
  • A language-lawyer quibble: That section of the C standard is actually somewhat poorly worded. It says that in the expression `sizeof arr`, the expression `arr` is evaluated, but it's not clear what that means. `arr` is an expression of array type; its value consists of the values of its elements. (The usual decay to a pointer doesn't happen in this context.) But `sizeof arr` certainly doesn't need to evaluate the array itself, it only needs to determine how big it is, and that information comes from the type, not from the value. But I'm not sure how I'd re-word it. – Keith Thompson Aug 17 '11 at 16:13
  • @Keith, Just thinking out loud here, but but what if i had `sizeof(arrparr[++i])`, where `arrparr` was something like `int (*int[6])[t]`. In that case evaluating the expression would have a side effect of incrementing `i`, or of invoking undefined behavior (generally a segfault) if it was a null pointer. I just tried this. CLANG does increment `i` in this case, but GCC 4.1.2 does not. CLANG either did not bother to preform the dereference, or it was optimized away (perfectly legal since only a null pointer matters, and dereferencing that is undefined behavior, thus doing nothing is legal). – Kevin Cathcart Aug 17 '11 at 18:59
  • Looking closer I see that CLANG does perform the dereference, but it is optimized away. Also I should clarify that any invalid pointer matters, not just the null pointer, but the compiler may still do nothing in that case. – Kevin Cathcart Aug 17 '11 at 19:06
2

In C99, the compiler is smart enough to know that rand() is called during run-time.

  • LOL, as opposed to dumb C89 compilers :) – pmg Aug 17 '11 at 13:51
  • Well ... it isn't the `rand()` that makes the array special. This snippet: `int k=42; int arr[k]; sizeof arr;` has an array just as special as the OP's. – pmg Aug 17 '11 at 14:00
  • @pmg: I'm not following you. It seems that the rand() generates a random number and that is used in the array size. –  Aug 17 '11 at 14:03
  • 2
    Yes, but the `sizeof` operator "works" because of 2 things: the array is a VLA and the compiler is C99 conformant. Try this with a C89 compiler: `const int k=42; int arr[k]; sizeof arr;` – pmg Aug 17 '11 at 14:18
  • @Code Monkey: Yes. What the two cases have in common is that the array length is computed at run time, at least in principle. – Keith Thompson Aug 17 '11 at 14:23
2

When using sizeof with VLAs (Variable Length Arrays) introduced in C99, their size is evaluated at runtime rather than compile time.

See a very nice reference on the subject here

Vinicius Kamakura
  • 7,665
  • 1
  • 29
  • 43