1

I'm curious about this one:

int main()
{
    int a[7];
    std::cout << "Length of array = " << (sizeof(a)/sizeof(*a)) << " - " << sizeof(a) << " - " << sizeof(*a) << std::endl;
}

Returns

Length of array = 7 - 28 - 4

So my question is: Why do I have to use (sizeof(a)/sizeof(*a)) to receive the right size, and why does sizeof(*a) returns 4, but sizeof(a) returns 28?

  • 1
    Because `a` and `*a` are different things with different type with different sizes. – tkausl Jan 09 '21 at 04:17
  • Got that, thanks. But why doing `(sizeof(a)/sizeof(*a))` gives us the right size of the array? And how comes they return that number, and nothing else? – lmao samoara Jan 09 '21 at 04:20
  • Note that this is not a discussion forum, but a Q&A site. There must be only one question per question. – cigien Jan 09 '21 at 04:23
  • 2
    @lmaosamoara `*a` is the same as `a[0]`. Then `sizeof(a[0])` gives you the size of one element, while `sizeof(a)` gives you the size of the entire array. Their ratio is the number of elements. – dxiv Jan 09 '21 at 04:23
  • If you work out what `a` and `*a` is, you should be able to figure out the answer yourself. Just ask yourself: what is `a`? what is `*a`? What does each one mean? – Sam Varshavchik Jan 09 '21 at 04:23
  • 1
    Because, when `a` is an array, `sizeof(a)` gives the size of the array in total, whereas `sizeof(*a)` gives the size of the array element. Arrays are specified as being a set of contiguous elements, all of the same type. So `sizeof(a)` is the size of an array of seven `int`, and `sizeof(*a)` is the size of an `int`. This means `sizeof(a) == 7 * sizeof(*a)`. – Peter Jan 09 '21 at 04:26

5 Answers5

4

sizeof(a) returns 28 because you have 7 elements in the array, and each element is 4 bytes long.

sizeof(*a) returns 4 because *a dereferences the first element in the array (an integer) which is 4 bytes long.

Thus, sizeof(a) / sizeof(*a) == 28/4 == 7

EDIT: You shouldn't make a habit of finding the length of an array this way in c++. It is much better to keep another variable around which stores the length of the array. sizeof is computed at compile-time with fixed-length arrays. If you call sizeof on a variable length array, it will usually return 8 as this is the size of a pointer (on 64 bit systems). See here for more information on this.

Jacob Blomquist
  • 276
  • 1
  • 5
  • 2
    You can use `std::size` to get the number of elements in an array. – Aykhan Hagverdili Jan 09 '21 at 09:40
  • Since variable length arrays do not exist in standard C++, there's no need to worry about how to manage them. And note that 8 is certainly not "the size of a pointer"; it might be on the system you're using, but there is no requirement of any particular size, and the sizes of pointers vary depending on the hardware an OS (if any). Same thing for "an integer ... is four bytes long". – Pete Becker Jan 09 '21 at 15:39
2

a, and *a have different type; int[7] and int respectively (ignoring possible reference as l-value).

We have:

  • sizeof(a[0]) = sizeof(*a) = sizeof (int)
  • sizeof(a) = sizeof (int[7]) = 7 * sizeof (int)
  • sizeof(a)/sizeof(*a) = std::extent<int[7]>::value = 7

It appears that, for your configuration, sizeof(int) == 4.

Jarod42
  • 203,559
  • 14
  • 181
  • 302
0

The name of an array decays into a pointer to the first element.

*a == a[0]
*(1+a) == a[1]

And so on.

So, an integer pointer is 4 bytes long, just like an int variable.

On the other hand, the a array is an integer array of length 7, so the overall size is 7 * 4 = 28

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • 3
    Nothing here has to do with pointers though, so I'm a bit confused with the statement _"So an integer pointer is 4 bytes long just like an int variable."_ A pointer isn't necessarily 4 bytes long (at least not on a modern 64-bit OS). I think it's better to say something like _"So the integer is 4 bytes in size (in this case)."_ – Ted Klein Bergman Jan 09 '21 at 04:46
  • Ted is correct. The `*a` is a de-reference. So it is an integer literal... thus 4 bytes. – Jacob Blomquist Jan 09 '21 at 05:09
  • "*The name of an array decays into a pointer*" Except `sizeof(a)` in OP's question is one of the cases where the array name does *not* decay into a pointer. See [Exceptions to array decaying into a pointer?](https://stackoverflow.com/questions/17752978/exceptions-to-array-decaying-into-a-pointer). – dxiv Jan 09 '21 at 05:15
0

a decays to a pointer when it is passed to a function, used in an operator, or pretty much used like a variable in any way. *a is referring to what the decayed pointer points to. In other words, a decays to an int* which points to the first value in a, while *a is an int, which is why sizeof is returning different sizes with the two data types.

Xiongmao
  • 1
  • 2
  • "`a` *is an* `int*`" This is *not* true for `sizeof(a)` which is part of OP's question. – dxiv Jan 09 '21 at 05:49
  • Ah, I worded it incorrectly. I meant to say `a` decays to an `int*` that points to the first value in `a`, but I wanted to write it concisely. – Xiongmao Jan 10 '21 at 05:19
0

By the statement int a[7], you are declaring an array of integers of size 7 (Only 7 integer elements can be stored here). If you use the statement sizeof(a), you get the size of a. As you probably may know, it is 7 x 4. (Why 4? Because the size of an integer is 4 bytes). Therefore, if you need to get the real size of the array (i.e. the number of elements), you must divide it with the size of int.

Why do I have to use (sizeof(a)/sizeof(*a)) to receive the right size, and why does sizeof(*a) returns 4, but sizeof(a) returns 28?

To answer this, you must be aware that the array name is actually a pointer to the 1st element of the array (i.e. In this case, it points at a[0].) So, what is a[0]? It is an integer right? You can think of sizeof(*a) as sizeof(int). Since sizeof(int) returns 4, so will sizeof(*a). The reason why you get 7 (the correct answer) is because: sizeof(a) = 7 * 4, sizeof(*a) = 4, therefore (sizeof(a)/sizeof(*a)) = 7.

  • "The size of an integer is 4 bytes" -- on your system, perhaps. That is not required, and it is not true on many hardware/OS combinations. An `int` must be at least 2 bytes. – Pete Becker Jan 09 '21 at 15:42