Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does an array pointer store its size? [duplicate]

Tags:

arrays

c

pointers

#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:

  1. Where is the length(count/size) info stored when "a" is declared?
  2. Why is the length(count/size) info lost when "a" is passed to the test() function?
like image 820
Lion Avatar asked Dec 24 '10 07:12

Lion


2 Answers

There's no such thing as "array pointer" in C language.

The size is not stored anywhere. a is 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 to the function you are intentionally asking the compiler to convert array type to pointer type (since you declared the function parameter as a pointer). For pointers your sizeof expression produces a completely different result.

like image 193
AnT Avatar answered Sep 28 '22 07:09

AnT


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

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

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

Unfortunately, in C, array parameters to functions are a fiction. Arrays don't get passed to functions; the parameter is treated as a pointer, and the array argument passed in the function call gets 'decayed' into a simple pointer. The sizeof operator returns the size of the pointer, which has no correlation to the size of the array that was used as an argument.

As a side note, in C++ you can have a function parameter be a reference to an array, and in that case the full array type is made available to the function (i.e., the argument doesn't decay into a pointer and sizeof will return the size of the full array). However, in that case the argument must match the array type exactly (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;
}
like image 34
Michael Burr Avatar answered Sep 28 '22 08:09

Michael Burr