# Sizeof confusion

I am a little confused concerning the usage of sizeof with arrays. On page 65 of the lecture notes it says: However three lines later there is this note which seems to contradict the first statement: Can someone clarify this for me? Is sizeof(numbers) 400000 because we get the size of 100000 pointers and because we know that when sizeof(int)=4, sizeof(*int)=4?

1 Like

There is an important difference between an array which is statically declared with type `int[]`, and a pointer to the first element of an array. First of all, the type `int[]` is really the type `int[N]` in disguise in the example below (actually not in all contexts…), where `N` is the length of the array. The length is therefore part of the type itself.

``````int x[] = { 2, 3 };
``````

Here `x` is declared with type `int` by syntactic sugar. So what is the type of `x`? Now, C is a complicated language, the type of an expression also depends on the context it is evaluated in, so the type of `x` may be different from the type of its declaration. In evaluated context, the type of `x` will be `int *` instead of `int`. This is so-called array-to-pointer conversion, which happens for example when you pass `x` to a function expecting a `int*` or when performing pointer arithmetic with `x`.

`sizeof` however does not evaluate its operand, here the type of `x` will be the type it was declared with, so `int`. The beginner’s mistake the script refers to is not to use `sizeof` on a variable declared with array type, but to use it on a pointer value which merely points to an array. Consider the following situation:

``````int x[] = { 2, 3 };
int* y = x;
// int z[] = x; Not even allowed
``````

What is `sizeof(y)`? Although `y` points to an array, the type `y` was declared with is `int*`, so `sizeof(y) = sizeof(int*)`. `sizeof` cannot retreive the length of the array that we point to, since it only gives the size of a type, and the length of the arraywe point to is not part of the declared type of `y` at all. On the contrary, we have `sizeof(x) = sizeof(int) = 2 * sizeof(int)`.

Note also that there is no rule that states `sizeof(int) = sizeof(int*)`, these sizes can actually be different.

4 Likes

You might wonder: When does this happen? The answer is: almost always. There are only four cases where it does not happen, namely

when it [the array] is the operand of the `sizeof` operator, the `_Alignof` operator, or the
unary `&` operator, or is a string literal used to initialize an array

Let’s look at these:

• `sizeof`: Thorsten has already explained this in the post above
• `_Alignof`: `_Alignof` works a bit like `sizeof`. Where `sizeof` gives you the size of an object (i.e. an array), `_Alignof` gives you the alignment. For example, `int`s typically have an alignment of `4`. Arrays usually inherit their alignment from their elements, so an array of `int` would also have an alignment of `4`. Apart from this, these operators are evaluated to numbers at compile-time and behave pretty similar (except that they yield different numbers)
• `&`: When you write `&numbers` in the above example, you get a value of type "pointer to array of `int`". Such an object is pretty weird, and there is really not much you can do with it, except use `*` to dereference it and get the pointer back. Since `*` and `&` cancel, this feature is mostly useless.
• Initializing an array: This refers to declarations like `char c[] = "Hello"`. This is just syntactic sugar for `char c[] = {'H', 'a', 'l', 'l', 'o', '\0'}`. But, since `"Hello"` is a string literal, and thus has type `char[]`, this needs to be explicitly said because this is the C standard, which tries to make everything explicit.

So, these are the four exceptions. Everywhere else you encounter something of type "array of t", this just automatically becomes a "pointer to t". Note that these exceptions are all syntactic. So you can always tell whether your array is converted by looking at the context the array is used in.

5 Likes