2

I, for a while, assumed that under the hood, variables that stored arrays were really just pointers to the first element of the array since, for example, char argv[][] and char **argv seem to be interchangeable but recently learned that the sizeof operator correctly returns the size of the underlying array. So are array variables stored as wide pointers? Why does sizeof fail when the array is passed to a function?

I'm sorry this may be a bit but as someone coming from low level Rust, arrays in C are really confusing me.

  • 1
    Welcome to SO. Arrays are not stored as pointers at all. They are stored as sequence of elements. The fact that the array name decays to a pointer in some cases (like the case when you pass an array to a function), does not make it a pointer. You might take a step back and revisit the learning material about arrays. Any decent tutorial should explain that as well. – Gerhardh Jul 05 '23 at 06:48
  • 1
    Your assumption is wrong, an array is *not* a pointer. But with that said, an array can *decay* to a pointer to its first element. If you have an array like `int arr[5];` it will be stored as five consecutive `int` elements in memory. When you need a pointer to its first element then you use plain `arr` which the compiler will decay to `&arr[0]`. This array to pointer decay might be a little confusing at first, but give it time and it will become natural. – Some programmer dude Jul 05 '23 at 06:48
  • Also note that once an array has decayed to a pointer, all you have is the pointer itself, you can't go back from the pointer to the array. Take the example array `arr` in my previous comment, if you have e.g. `int *ptr = arr;` then that will make `ptr` point to the first element of the array. But `ptr` *only* points to a single `int` value, the pointer variable or the compiler itself have no knowledge that it's pointing to an element in an array. – Some programmer dude Jul 05 '23 at 06:50
  • `char argv[][]` and `char **argv` are *never* interchangeable. In fact, `char argv[][]` isn't even a valid type. You're thinking of `char *argv[]`, which is converted to a `char **argv` in various contexts. – Tom Karzes Jul 05 '23 at 06:52
  • This might be helpful: https://stackoverflow.com/questions/21604946/pointer-to-pointer-clarification – Lundin Jul 05 '23 at 06:52
  • Quote: "... but the pointer in the named variable)" It's not stored in memory. The compiler knows where the array is located and for array access the compiler generates code that reads/writes the array location. – Support Ukraine Jul 05 '23 at 07:00
  • Ok thank you all! Yeah the point about the arrays decaying into pointers really confused me. Is there a reason why you can't pass an array as an argument like in rust and why it always decays? – Mindustry Logic Processor Jul 05 '23 at 07:10
  • 1
    @MindustryLogicProcessor "Is there a reason why you can't pass an array as an argument like ... why it always decays?" because the C language is defined that way. It was deemed a good design at the time and given 40+ years of use, was at least a reasonable choice. – chux - Reinstate Monica Jul 05 '23 at 07:21
  • @chux-ReinstateMonica Fair enough. – Mindustry Logic Processor Jul 05 '23 at 07:35
  • @MindustryLogicProcessor " Is there a reason why you can't pass an array..." Well, copying a whole array would not be good for performance. Further, a big array would take up a lot of stack memory (risk of overflow). It's seldom that a function needs a copy of the original array. And if a function really needs a copy of the original array, the function can always start out making that copy. That said, the C standard could of cause have included a "pass array by value" option but the designers probably just deemed it unnecessary. – Support Ukraine Jul 05 '23 at 07:40

1 Answers1

4

How are array variables stored in C? (not the memory itself but the pointer in the named variable)

Arrays are stored like other objects: an int, a struct, etc. Each exists in memory, starting at some address*1 and occupying sizeof object bytes.

An object, being an array or not, has an address. Each element of an array has an address.

are array variables stored as wide pointers?

No.

Why does sizeof fail when the array is passed to a function?

sizeof does not fail. It is that when an array is passed to a function, it is first converted to the type and address of the first element. The function receives a pointer, not an array. The below prints the size of the array a (e.g. 12) and then the size of the pointer ptr (e.g. 2, 4, or 8). Expecting sizeof ptr to be the size of an array is not a failure on the language's part.

int foo(int *ptr) {
  printf("%zu\n", sizeof ptr);
  return 0;
}

int main() {
  int a[3] = { 1,2,3,};
  printf("%zu\n", sizeof a);
  return foo(a);
}

arrays in C are really confusing me.

Remembering that arrays are not pointers and pointers are not arrays is useful.

Is there a reason why you can't pass an array as an argument like in rust and why it always decays?

... because the C language is defined that way. It was deemed a good design at the time and given 40+ years of use, was at least a reasonable choice.


*1 An object stored in a register has no address.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256