[ACCEPTED]-determine size of array if passed to function-pointers

Accepted answer
Score: 63

The other answers overlook one feature of 5 c++. You can pass arrays by reference, and 4 use templates:

template <typename T, int N>
void func(T (&a) [N]) {
    for (int i = 0; i < N; ++i) a[i] = T(); // reset all elements
}

then you can do this:

int x[10];
func(x);

but note, this 3 only works for arrays, not pointers.

However, as 2 other answers have noted, using std::vector is a better 1 choice.

Score: 15

If it's within your control, use a STL container 2 such as a vector or deque instead of an 1 array.

Score: 9

Nope, it's not possible.

One workaround: place 2 a special value at the last value of the 1 array so you can recognize it.

Score: 6

One obvious solution is to use STL. If it's 15 not a possibility, it's better to pass array 14 length explicitly. I'm skeptical about use 13 the sentinel value trick, for this particular 12 case. It works better with arrays of 11 pointers, because NULL is a good value for 10 a sentinel. With array of integers, it's 9 not that easy - you need to have a "magic" sentinel 8 value, which is not good.

Side note: If 7 your array is defined and initalized as

 int array[] = { X, Y, Z };

in 6 the same scope as your loop, then

sizeof(array) will 5 return it's real size in bytes, not the 4 size of the pointer. You can get the array 3 length as

sizeof(array) / sizeof(array[0])

However, in general case, if you 2 get array as a pointer, you can't use this 1 trick.

Score: 4

You could add a terminator to your int array 6 then step through the array manually to 5 discover the size within the method.

#include<iostream>
using namespace std;

int howBigIsBareArray(int arr[]){
    int counter = 0;
    while (arr[counter] != NULL){
        counter++;
    }
    return counter;
}
int main(){
    int a1[6] = {1,2,3,4,5,'\0'};
    cout << "SizeOfMyArray: " << howBigIsBareArray(a1);
}

This 4 program prints:

SizeOfMyArray: 5

This is an O(n) time complexity 3 operation which is bad. You should never 2 be stepping through an array just to discover 1 its size.

Score: 3

If you can't pass the size, you do need 8 a distinguishable sentinel value at the end (and 7 you need to put it there yourself -- as 6 you've found, you can't trust C++ to do 5 it automagically for you!). There's no 4 way to just have the called function magically 3 divine the size, if that's not passed in 2 and there is no explicit, reliable sentinel 1 in use.

Score: 1

Can you try appending a null character \0 to 2 the array and then send it? That way, you 1 can just check for \0 in the loop.

Score: 1

Actually Chucks listing of

for( int i = 0; array[i] != NULL; i++) { ........ }

A 12 sizeof before each call is wasteful and 11 is needed to know what you get.

Works great 10 if you put a NULL at the end of the arrays.

Why?? With 9 embedded designs passing a sizeof in each 8 routine makes each call very large compared 7 to a NULL with each array. I have a 2K PIC16F684 6 chip and it takes upto 10 percent of the 5 chip with 12 calls using a passed sizeof 4 along with the array. With just the array 3 and Chucks code with NULLS om each array... I 2 get 4 percent needed.

A true case in point.. thanks 1 chuck good call.

Score: 0

I originally had this as an answer to this other question: When a function has a specific-size array parameter, why is it replaced with a pointer?, but just moved it here instead since it more-directly answers this question.


Building off of @Richard Corden's answer and @sbi's answer, here's a larger example 20 demonstrating the principles of:

  1. Enforcing 19 a given function parameter input array size 18 using a reference to an array of a given 17 size, like this:

     void foo2(uint8_t (&array)[100]) 
     {
         printf("sizeof(array) = %lu\n", sizeof(array)); 
     }
    

    and:

  2. Allowing a function 16 parameter input array of any size, by using 15 a function template with a reference to an input 14 array of a given template parameter size 13 N, like this:

     template<size_t N>
     void foo3(uint8_t (&array)[N])
     {
         printf("sizeof(array) = %lu\n", sizeof(array)); 
     }
    

Looking at the full example below:

Notice how this function prototype 12 doesn't know the array size at all! (the 100 here 11 is simply a visual hint/reminder to the 10 human user, but has no bearing or influence on the 9 compiler whatsoever!):

void foo(uint8_t array[100]) {}

...this function prototype 8 allows only input arrays of a fixed size 7 of 100:

void foo2(uint8_t (&array)[100]) {}

...and this function template prototype allows 6 arrays of ANY input size AND knows their 5 size statically at compile-time (as that 4 is how templates work):

template<size_t N>
void foo3(uint8_t (&array)[N]) {}

Here's the full example:

You can run it yourself 3 here: https://onlinegdb.com/rkyL_tcBv.

#include <cstdint>
#include <cstdio>

void foo(uint8_t array[100]) 
{
    // is ALWAYS sizeof(uint8_t*), which is 8!
    printf("sizeof(array) = %lu\n", sizeof(array)); 
}

void foo2(uint8_t (&array)[100]) 
{
    printf("sizeof(array) = %lu\n", sizeof(array)); 
}

template<size_t N>
void foo3(uint8_t (&array)[N])
{
    printf("sizeof(array) = %lu\n", sizeof(array)); 
}


int main()
{
    printf("Hello World\n");
    printf("\n");
    
    uint8_t a1[10];
    uint8_t a2[11];
    uint8_t a3[12];
    
    // Is `sizeof(array) = 8` for all of these!
    foo(a1);
    foo(a2);
    foo(a3);
    printf("\n");
    
    // Fails to compile for these 3! Sample error:
    // >     main.cpp:49:12: error: invalid initialization of reference of type ‘uint8_t (&)[100] 
    // >     {aka unsigned char (&)[100]}’ from expression of type ‘uint8_t [10] {aka unsigned char [10]}’
    // >          foo2(a1);
    // >                 ^
    // foo2(a1);
    // foo2(a2);
    // foo2(a3);
    // ------------------
    // Works just fine for this one since the array `a4` has the right length!
    // Is `sizeof(array) = 100`
    uint8_t a4[100];
    foo2(a4);
    printf("\n");

    foo3(a1);
    foo3(a2);
    foo3(a3);
    foo3(a4);
    printf("\n");

    return 0;
}

Sample output:

(compiler warnings, referring to 2 the sizeof call inside foo()):

main.cpp:26:49: warning: ‘sizeof’ on array function parameter ‘array’ will return size of ‘uint8_t* {aka unsigned char*}’ [-Wsizeof-array-argument]                               
main.cpp:23:27: note: declared here                                                                                                                                               

(stdout "standard 1 output"):

Hello World                                                                                                                                                                       
                                                                                                                                                                                  
sizeof(array) = 8                                                                                                                                                                 
sizeof(array) = 8                                                                                                                                                                 
sizeof(array) = 8                                                                                                                                                                 
                                                                                                                                                                                  
sizeof(array) = 100                                                                                                                                                               
                                                                                                                                                                                  
sizeof(array) = 10                                                                                                                                                                
sizeof(array) = 11                                                                                                                                                                
sizeof(array) = 12                                                                                                                                                                
sizeof(array) = 100   
Score: 0

Shouldn't this work? for things like Arduino(AVR) c++ at 1 least.

//rename func foo to foo_ then
#define foo(A) foo_(A, sizeof(A))

void foo_(char a[],int array_size){
...
}

More Related questions