How does an array pointer store its size?

#include "stdio.h" #define COUNT(a) (sizeof(a) / sizeof(*(a))) void test(int b[]) { printf("2, count:%d\n", COUNT(b)); } int main(void) { int a[] = { 1,2,3 }; printf("1, count:%d\n", COUNT(a)); test(a); return 0; } 

The result is obvious:

 1, count:3 2, count:1 

My questions:

  • Where is the length information (invoice / size) stored when "a" is declared?
  • Why is length information (score / size) lost when "a" is passed to the test () function?
+4
source share
6 answers

In C, there is no such thing as an "array pointer".

Size is not saved anywhere. a not a pointer, a is an object of type int[3] , which is a fact well known to the compiler at compile time. So, when you ask the compiler to calculate sizeof(a) / sizeof(*a) at compile time, the compiler knows that the answer is 3 .

When you pass your a function, you intentionally ask the compiler to convert the array type to a pointer type (since you declared the function parameter as a pointer). For pointers, your sizeof expression gives a completely different result.

+7
source
  • Where is the length information (invoice / size) stored when "a" is declared?

It is not stored anywhere. The sizeof operator (used in the COUNT() macro) returns the size of the entire array when it sets the true array as an operand (as in the first printf() )

  1. Why is length information (score / size) lost when "a" is passed to the test () function?

Unfortunately, in C, array parameters for functions are fictitious. Arrays are not passed to functions; the parameter is treated as a pointer, and the array argument passed in the function call gets "fades out" into a simple pointer. The sizeof operator returns the size of the pointer, which does not correlate with the size of the array that was used as the argument.

As a side note in C ++, you can have a function parameter as a reference to an array, in which case the full type of the array becomes available to the function (i.e. the argument does not break into a pointer and sizeof returns the size of the full array). However, in this case, the argument must exactly match the type of the array (including the number of elements), which makes the technique mostly useful only with templates.

For example, the following C ++ program will do what you expect:

 #include "stdio.h" #define COUNT(a) (sizeof(a) / sizeof(*(a))) template <int T> void test(int (&b)[T]) { printf("2, count:%d\n", COUNT(b)); } int main(int argc, char *argv[]) { int a[] = { 1,2,3 }; printf("1, count:%d\n", COUNT(a)); test(a); return 0; } 
+5
source
  • Nowhere.
  • Because it was not saved in the first place.

When you reference an array in main() , the actual definition of the declare array is visible, so sizeof(a) gives the size of the array in bytes.

When you reference an array in a function, the parameter is effectively " void test(int *b) , and the size of the pointer divided by the size of the thing it points to is 1 on a 32-bit platform, whereas it will be 2 on a 64-bit a platform with an LP64 architecture (or, indeed, an LLP64 platform such as Windows-64), since pointers are 8 bytes and int are 4 bytes.

There is no universal way to determine the size of an array passed to a function; you must pass it explicitly and manually.


From the comment:

I still have two questions:

  • What do you mean by ".. the actual ad is visible ..."? [T] could the compiler (or OS) get length information through the sizeof (a) function?
  • Why doesn't the & (a [0]) pointer contain length information like the "a" pointer?
  • I think you learned Java before you learned C, or some other more modern language. Ultimately, it boils down to "because that's how C is defined." OS is not involved; this is a problem with the compiler.

    • sizeof() is an operator, not a function. If you are not dealing with a VLA (variable length array), it is computed at compile time and is a constant value.

    Inside main() is an array definition (I mean when I said โ€œdeclarationโ€), there is also when the sizeof() operator is applied to the name of the actual array - unlike the array parameter to the function - then the returned size is the size of the array in bytes .

  • Because it is C, not Algol, Pascal, Java, C #, ...

    C does not save the size of the array - period. This is a fact of life. And, when the array is passed to the function, size information is not passed to the function; the array "decays" into a pointer to the zero element of the array - and only that pointer is passed.

+1
source
  • Where is the length information (invoice / size) stored when "a" is declared?

Nowhere. The question does not make sense BTW.

  1. Why is length information (score / size) lost when "a" is passed to the test () function?

The array decays to a pointer (to the first element) when passing a function. So the answer is โ€œnowhereโ€ and similar to the previous question, this again makes no sense.

+1
source
 1. Where is the length(count/size) info stored when "a" is declared? 

It is not saved. The compiler knows what a is, and therefore knows its size. Thus, the compiler can replace sizeof() with the actual size.

 2. Why is the length(count/size) info lost when "a" is passed to the test() function? 

In this case, b is declared as a pointer (although it may point to a). Given the pointer, the compiler does not know the size of the specified data.

+1
source

Array pointer does not save size. However, the type [] is not really a pointer. This is a different type. When you say int a[] = {1,2,3}; , you define an array of three elements, and since it is defined like this, sizeof (a) gives you the size of the entire array.

If you specify the parameter as int a [], it is almost the same as int * a, and sizeof (a) will be the size of the pointer (which by coincidence may be the same as the size of int , but not always).

There is no way in C to save size in a pointer type, so if you need size, you need to pass it as an additional argument or use struct .

0
source

Source: https://habr.com/ru/post/1333270/


All Articles