1

If I have:

int a[] = {1,2,3};
int len = sizeof(a) / sizeof(int);

I get 3, and I don't understand why.

They always taught me that an array is a pointer, doesn't store its length, but only the pointer to the first element.

Can someone explain this to me in a better way?

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
GDG612
  • 129
  • 1
  • 10
  • 7
    Whoever taught you that an array is a pointer was very wrong, as you can see from this example. Just ignore it. I'm not sure what there is to explain. `sizeof(a)` gives you the size of the array in bytes. – juanchopanza Mar 09 '16 at 21:29
  • I guess my statement was an oversimplification of what i intended to say. Not wrong, but oversimplified. Point taken. Will remove comments – SandBag_1996 Mar 09 '16 at 21:44
  • @UnderDog Or just plain wrong. At least, it is a mental model that causes so much confusion as to be counter-productive. – juanchopanza Mar 09 '16 at 21:55
  • @juanchopanza, I wont stoop down and argue on such levels. It was not plain wrong, it was an oversimplified version of what I wanted to say. It "can be" treated as a constant pointer to first element. I will zip it and move on. seems you have lot of time on your hands to issue such demeaning statements. – SandBag_1996 Mar 09 '16 at 22:00
  • @UnderDog Given that this is a question about why an array *isn't* a pointer, I don't think pointing out that your oversimplification is wrong is stooping down to any level. There's already too much confusion about that, and it gets tedious to see more people perpetrating it. – juanchopanza Mar 09 '16 at 22:04

4 Answers4

4

An array decays to a pointer to the first element of the array in most expressions. There are two cases where it does not and hence the outcome is not the same.

int array[5];
int* ptr = array;   // Array decays to a pointer, OK.

// Same
int a = array[0];
int a = ptr[0];

// Same
void foo(int*);
foo(array);
foo(ptr);

// Not same
size_t s = sizeof(array);  // s is 5*sizeof(int)
size_t s = sizeof(ptr);    // s is sizeof(int*)

// Not same
int (*p1)[5] = &array;     // p1 is a pointer to "an array of 5 ints"
int **p1 = &ptr;           // p1 is a pointer to "an int*"
R Sahu
  • 204,454
  • 14
  • 159
  • 270
4

sizeof a returns the size of the entire array in storage units (bytes). sizeof (int) returns the size of a single integer in storage units. Since a is an array of 3 integers, sizeof a / sizeof (int) gives you 3.

They always taught me that an array that it is a pointer

"They" taught you incorrectly. Unless it is the operand of the sizeof or unary & operators, an array expression will be converted ("decay") to a pointer expression, and the value of the pointer expression will be the address of the first element of the array, but an array object is not a pointer.

When you declare a, what you get in memory looks something like this:

  +---+
a:|   | a[0]
  +---+
  |   | a[1]
  +---+
  |   | a[2]
  +---+

There is no object a that's separate from the array elements; there's no pointer anywhere.

John Bode
  • 119,563
  • 19
  • 122
  • 198
3

They always taught me that an array that it is a pointer

That's your problem, right there. When you call a function and pass an array as an argument, it gets converted into a pointer to the first element. Otherwise, they're not equivalent. In particular, an array has an address, a type, and a size, whereas a pointer just has an address and a type.

This is a pretty common confusion among people learning C for the first time, and even some textbooks get it wrong.

edit: there are a few other cases where arrays "decay" to pointers, typically when they're used in an expression. See one of the other fine answers for a more-exhaustive treatment.

Mark Bessey
  • 19,598
  • 4
  • 47
  • 69
  • "When you call a function and pass an array as an argument, it gets converted into a pointer to the first element." If the parameter is a pointer. The key is that the parameter has to be a pointer, and pointer is just a pointer. – juanchopanza Mar 09 '16 at 21:37
  • 2
    @juanchopanza: There's no “if”; passing an array as a function argument *always* causes it to decay to a pointer. If you declare `int f(int a[])`, it's as if you had written `int f(int *a)`, and `sizeof(a)` inside the function will return the size of a pointer. – dan04 Mar 09 '16 at 21:46
  • @dan04 The point is that a function can't have an array as parameter. So one doesn't even have to consider the possibility that one is dealing with an array, because the parameter is a pointer. Either that, or passing an array as argument will result in compiler error. – juanchopanza Mar 09 '16 at 21:48
  • 1
    Of course, it's not just "When you call a function and pass an array as an argument". It's whenever an array appears in an expression, other than just to the right of `&` or `sizeof`. – Steve Summit Mar 09 '16 at 21:53
  • @SteveSummit, that's a good point. I'll edit the answer a bit. – Mark Bessey Mar 10 '16 at 01:04
1

An array can decay to a pointer, but that does not mean an array is a pointer. See this SO question for details.

sizeof returns the size (in bytes) of the data type of its operand. In this case, the data type is an array of int of length three. But, since an int can be represented in different ways on different platforms, you must divide by the sizeof(int) to get the length.

See here for more details on sizeof.

Community
  • 1
  • 1
Rob Jones
  • 4,925
  • 3
  • 32
  • 39