3

I have a pointer to an array in C which I would like to iterate through, but I don't know the size:

int *array;

I am unsure as to how I should proceed. I was thinking that I should probably try by finding the size by doing:

int array_size = sizeof(array) / sizeof(int);

But I don't know if that could work. I was wondering if there was a more optimal way of doing this?

Armen Michaeli
  • 8,625
  • 8
  • 58
  • 95
a_confused_student
  • 349
  • 1
  • 3
  • 13
  • If all you have is the pointer then you are out of luck. Either the size must be passed in to the function of the array contents must have a terminator that indicates the end of the array. – kaylum Apr 25 '21 at 11:16
  • `sizeof(array)/sizeof(int)` will not work if you only have the pointer and not the original array definition. `sizeof(array)` in that case would be `sizeof(int *)` which is always going to be the size of one pointer. – kaylum Apr 25 '21 at 11:16
  • even with a while loop it wouldn't work? – a_confused_student Apr 25 '21 at 11:20
  • The type of loop is irrelevant if you don't have the size or a terminating value. How do you propose ending the loop without the size or terminating value? You can't. – kaylum Apr 25 '21 at 11:21
  • If you look closely at functions in C libraries that take pointers you'll always find that there is either a special element value that can serve as a terminator (char strings, argv), or a second parameter for passing the length (memcpy). That's the only two ways. – Peter - Reinstate Monica Apr 25 '21 at 11:42
  • 1
    The most important thing I cannot see anyone telling you straight out is that what you have is not an array. It's just a pointer. An array has fixed size in C declared with `[]` and that would allow you to iterate over one conveniently. Without a fixed size it's not an array. Of course, your `array` *may be pointing* to some memory allocated for an array, but that doesn't make `array` an array, and the C compiler is also of that opinion. – Armen Michaeli Apr 25 '21 at 12:09

4 Answers4

4

In C, there is no way to tell the number of elements in an array from a pointer to an element. sizeof(array) / sizeof(*array) only works for an actual array, not for a pointer, which is what a function receives as an argument, even if the array syntax is used in the function prototype. In this case sizeof(array) evaluates to the size of the pointer, so dividing that by the size of an element is meaningless.

The best approach for your function to get the number of elements is to provide it as a separate argument.

If this is not practical, there are different ways to infer the number of elements, relying on a convention that must be adhered to by the callers:

  • the array could have a known fixed number of elements

  • the array could have a sentinel value as the last element of the array.

    It is common to use a null pointer (NULL) as such a sentinel for arrays of pointers, such as the char *argv[] argument of the main() function, but note that int argc is also provided to this function.

    The null byte (\0) is used to tell the end of C strings, which are arrays of char.

    In your case, you could consider 0 or -1 to signify the end of the array, but this convention must be used consistently by all callers of your function.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
2

You cannot iterate over an array in c without knowking the number of elements.

Please note that sizeof(array) / sizeof(array[0]) won't work on a pointer, i.e it will not give the number of elements in the array.

It will also not work inside a function, where the array was passed as an argument due to array decay to pointer.

Kfir Ventura
  • 262
  • 2
  • 9
2

If the array does not contain a known sentinel value (as for example character arrays that contain strings have as the sentinel value the terminating zero character '\0') then you can not find its end.

If you have a pointer like this

int *array;

then the expression sizeof( array ) will yield the size of the pointer itself that does not depend on whether the pointer points to a single object of the type int or to the first element of an integer array with a known number of elements in the array. That size for example can be equal either to 4 or 8 depending on the used system. Thus the expression sizeof( array ) / sizeof( int ) in general will always yield either 1 or 2.

So you have to pass to the function explicitly also the number of elements in the array.

You could determine the number of elements in an array if you pass a pointer to the whole array. For example

void f( int( *a )[10] );

//...

int a[10];

//...

f( &a );

In this case dereferencing the pointer within the function you will get an object of the array type. Thus the expression sizeof( *a ) will yield the size of the original array.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • 1
    I wanted to make the point with the pointer to whole array as well, but then didn't: While technically correct it is also pointless: If you know the size 10 (which you have to in order to declare the pointer), you can as well simply pass a pointer to the first element as usual and just iterate over the 10 elements. A pointer to an array is also truly un-idiomatic in C -- nobody uses it because of the above-said, so people would do a double take. – Peter - Reinstate Monica Apr 25 '21 at 11:38
  • @Peter-ReinstateMonica It is not exactly as you wrote because a function can be called according to a generic selection. – Vlad from Moscow Apr 25 '21 at 11:54
  • "Generic selection": Not sure what you mean --- can you give an example? – Peter - Reinstate Monica Apr 25 '21 at 12:35
  • @Peter-ReinstateMonica You can use _Generic for selecting a function for a concrete type of a pointer to an array. In tit is better in his case in all such functions to use expressions with the sizeof operator instead of directly use constants because the code is duplicated. – Vlad from Moscow Apr 25 '21 at 12:40
  • Interesting, I had never heard of it. Perhaps include an example in the answer! – Peter - Reinstate Monica Apr 25 '21 at 13:10
1

I have a pointer to an array in c to which I would like to iterate through but I don't know the size:

You are in luck if you truly have a pointer to an array as the type of a pointer to an array carries information about the array size.

  int some_array[7] = {1, 2, 3, 4, 5, 6, 7};
  int (*pointer_to_an_array)[7] = &some_array;

  #define N (sizeof(*pointer_to_an_array) / sizeof(*pointer_to_an_array[0]))
  for (size_t i = 0; i < N; i++) {
    printf("%d\n", (*pointer_to_an_array)[i]);
  }

  

Unfortunately, with int *array;, code does not have a pointer to an array, but a pointer to an int and information about the original array size of some_array[] is not available through array.

int some_array[7] = {1,2,3,4,5,6,7};
int *array = some_array; // Not a pointer to an array

Carry information about array size in another variable.

size_t some_array_n = sizeof some_array/ sizeof some_array[0];
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256