Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

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?

share|improve this question
5  
C or C++? Pick one. –  Lightness Races in Orbit Apr 22 '13 at 10:45
3  
What difference does it make whether it's c or c++? –  Pete Fordham Apr 22 '13 at 17:22
add comment

7 Answers

up vote 33 down vote accepted

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).

share|improve this answer
1  
+1: Hard to find anything wrong with this. And I did try! –  Lightness Races in Orbit Apr 22 '13 at 10:46
    
This bit me when I tried to use boost::begin() on a function with sized array as parameter. Doesn't work. Was just pointer.. meh. –  Macke Apr 22 '13 at 13:47
    
@Macke If that’s still relevant have a look at Morwenn’s answer, you can pass fixed-sized arrays to a function, albeit only by reference (but that should never be a problem). –  Konrad Rudolph Apr 22 '13 at 14:47
    
might be useful to cite the standard: C99 standard 6.7.5.3, para. 7, "A declaration of a parameter as "array of type" shall be adjusted to "qualified pointer to type" ..." –  newacct Apr 22 '13 at 18:22
    
Why is using std::string the correct way? It is no more correct or less correct that using pointers. There is a difference between typical/standard and correct. –  Thomas Eding Apr 22 '13 at 18:44
show 1 more comment

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

share|improve this answer
    
Or void func4( std::vector<char> const& str ). –  James Kanze Apr 22 '13 at 10:30
add comment

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()
{
    dummy("test"); // Works, N is 5
    return 0;
}
share|improve this answer
add comment

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.

share|improve this answer
1  
No, the third function does not pass an array of a fixed size. This would imply that there is a difference between those functions but there really is none. The type of all three functions is the same. If you want to provide a hint as to the expected array size, use a comment or documentation, that makes it clear that the size isn’t checked by the compiler. –  Konrad Rudolph Apr 22 '13 at 10:40
    
my bad, thank you. :D –  user2301717 Apr 22 '13 at 10:43
add comment

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].

share|improve this answer
1  
Might make it more explicit that the last code is valid C but not valid C++ (for the moment). –  Konrad Rudolph Apr 22 '13 at 11:37
    
@KonradRudolph Thanks for the suggestion. I've amended that section of my answer. –  undefined behaviour Apr 22 '13 at 15:21
add comment

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.

share|improve this answer
3  
It gives a bad idea about the size of the array. –  Lightness Races in Orbit Apr 22 '13 at 10:46
    
@LightnessRacesinOrbit I would never use the third syntax in any case.Just pointless to use that. –  Rüppell's Vulture Apr 22 '13 at 10:48
    
Indeed! Same here! –  Lightness Races in Orbit Apr 22 '13 at 10:49
add comment

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.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.