Difference between passing array, fixed-sized array and base address of array as a function parameter

C++ArraysPointers

C++ Problem Overview


I am confused about which syntax to use if I want to pass an array of known or unknown size as a function parameter.

Suppose I have these variants for the purpose:

void func1(char* str) {
    //print str
}

void func2(char str[]) {
    //print str
}

void func3(char str[10]) {
    //print str
}

What are the pros and cons of using each one of these?

C++ Solutions


Solution 1 - C++

All these variants are the same. C just lets you use alternative spellings but even the last variant explicitly annotated with an array size decays to a normal pointer.

That is, even with the last implementation you could call the function with an array of any size:

void func3(char str[10]) { }

func("test"); // Works.
func("let's try something longer"); // Not a single f*ck given.

Needless to say this should not be used: it might give the user a false sense of security (“oh, this function only accepts an array of length 10 so I don’t need to check the length myself”).

As Henrik said, the correct way in C++ is to use std::string, std::string& or std::string const& (depending on whether you need to modify the object, and whether you want to copy).

Solution 2 - C++

Note that in C++, if the length of the array is known at compile time (for example if you passed a string literal), you can actually get its size:

template<unsigned int N>
void func(const char(&str)[N])
{
    // Whatever...
}

int main()
{
    func("test"); // Works, N is 5
}

Solution 3 - C++

In C++, use void func4(const std::string& str) .

Solution 4 - C++

These are all functionally identical. When you pass an array to a function in C, the array gets implicitly converted to a pointer to the first element of the array. Hence, these three functions will print the same output (that is, the size of a pointer to char).

void func1(char* str) {
    printf("sizeof str: %zu\n", sizeof str);
}

void func2(char str[]) {
    printf("sizeof str: %zu\n", sizeof str);
}

void func3(char str[10]) {
    printf("sizeof str: %zu\n", sizeof str);
}

This conversion only applies to the first dimension of an array. A char[42][13] gets converted to a char (*)[13], not a char **.

void func4(char (*str_array)[13]) {
    printf("sizeof str_array: %zu\n"
           "sizeof str_array[0]: %zu\n", sizeof str_array, sizeof str_array[0]);
}

char (*)[13] is the type of str_array. It's how you write "a pointer to an array of 13 chars". This could have also been written as void func4(char str_array[42][13]) { ... }, though the 42 is functionally meaningless as you can see by experimenting, passing arrays of different sizes into func4.

In C99 and C11 (but not C89 or C++), you can pass a pointer to an array of varying size into a function, by passing it's size along with it, and including the size identifier in the [square brackets]. For example:

void func5(size_t size, char (*str_array)[size]) {
    printf("sizeof str_array: %zu\n"
           "sizeof str_array[0]: %zu\n", sizeof str_array, sizeof str_array[0]);
}

This declares a pointer to an array of size chars. Note that you must dereference the pointer before you can access the array. In the example above, sizeof str_array[0] evaluates to the size of the array, not the size of the first element. As an example, to access the 11th element, use (*str_array)[11] or str_array[0][11].

Solution 5 - C++

In C, the first two definitions are equivalent.The third one is essentially same but it gives an idea about the size of the array.

If printing str is your intent, then you can safely use any of them.Essentially all three of the functions are passed a parameter of type char*,just what printf() needs to print a string.And lest you don't know, despite what it may seem, all parameter passing in C is done in pass-by-value mode.

Edit: Seems like I'll have to be very rigorous in my choice of words on SO henceforth.Well,in the third case it gives no idea about the size of the array to the function to which it is passed as eventually it is reduced to type char* just as in the first two cases.I meant to say it kinda tells the human reading it that the array's size is 10.Also,it is not wrong/illegal in C.But for the program,doing it is as good as useless.It gives no idea whatsoever about the array size to the function it is passed to.Mr.Downvoter, thanks for pointing out that casual attitude and negligence is not tolerated on SO.

Solution 6 - C++

In a one dimensional array they are all treated the same by the compiler. However for a two or more dimensional array, (e.g. myArray[10][10]), it is useful as it can be used to determine the row/column length of an array.

Solution 7 - C++

To add-on, describing in points.

  1. As everyone told it is same.

  2. Arrays are decayed into pointers when they are passed in the function arguments.

  3. Fundamental problem could be finding the size of a array in the function. For that we can use macro like.

    #define noOfElements(v) sizeof(v)/sizeof(0[v])
    
    int arr[100]
    myfunction ( arr, noOfElements(arr))
    

    either 0[v] or v[0] can be used in the macro, where the first is used to avoid user defined data type passed in to noOfElements.

Hope this helps.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionmr5View Question on Stackoverflow
Solution 1 - C++Konrad RudolphView Answer on Stackoverflow
Solution 2 - C++MorwennView Answer on Stackoverflow
Solution 3 - C++HenrikView Answer on Stackoverflow
Solution 4 - C++autisticView Answer on Stackoverflow
Solution 5 - C++Rüppell's VultureView Answer on Stackoverflow
Solution 6 - C++user2301717View Answer on Stackoverflow
Solution 7 - C++WhoamiView Answer on Stackoverflow