Passing an array as a function parameter in C++
Use templates. This technically doesn't fit your criteria, because it changes the signature, but calling code does not need to be modified.
void doSomething(char charArray[], size_t size){ // do stuff here}template<size_t N>inline void doSomething(char (&charArray)[N]){ doSomething(charArray, N);}
This technique is used by Microsoft's Secure CRT functions and by STLSoft's array_proxy class template.
Without changing the signature? Append a sentinel element. For char arrays specifically, it could be the null-terminating '\0'
which is used for standard C strings.
void doSomething(char charArray[]){ char* p = charArray; for (; *p != '\0'; ++p) { // if '\0' happens to be valid data for your app, // then you can (maybe) use some other value as // sentinel } int arraySize = p - charArray; // now we know the array size, so we can do some thing}
Of course, then your array itself cannot contain the sentinel element as content.For other kinds of (i.e., non-char) arrays, it could be any value which is not legal data. If no such value exists, then this method does not work.
Moreover, this requires co-operation on the caller side. You really have to make sure that the caller reserves an array of arraySize + 1
elements, and always sets the sentinel element.
However, if you really cannot change the signature, your options are rather limited.
In general when working with C or low-level C++, you might consider retraining your brain to never consider writing array parameters to a function, because the C compiler will always treat them as pointers anyway. In essence, by typing those square brackets you are fooling yourself in thinking that a real array is being passed, complete with size information. In reality, in C you can only pass pointers. The function
void foo(char a[]){ // Do something...}
is, from the point of view of the C compiler, exactly equivalent to:
void foo(char * a){ // Do something}
and obviously that nekkid char pointer contains no length information.
If you're stuck in a corner and can't change the function signature, consider using a length prefix as suggested above. A non-portable but compatible hack is to specify the array length in an size_t field located before the array, something like this:
void foo(char * a){ int cplusplus_len = reinterpret_cast<std::size_t *>(a)[-1]; int c_len = ((size_t *)a)[-1];}
Obviously your caller needs to create the arrays in the appropriate way before passing them to foo.
Needless to say this is a horrible hack, but this trick can get out of trouble in a pinch.