The problem is that arrays in C are supposed to be well arrays.. but people often use them as shortcut to define some small non-standard chunk of data, and then you have a nice little surprise waiting to happen when your later upgrading or re-factoring or just using that piece of code. (otherwise know as the "30 seconds saved, 3 hours wasted" coding style..)
Here is what happens when you use arrays as a replacement type:
#include <iostream> void func(char c[5]) { std::cout << "sizeof(param,5):" << sizeof(c) << std::endl; } void func2(char c[14]) { std::cout << "sizeof(param,14):" << sizeof(c) << std::endl; } typedef char Typedefed[5]; void func3(Typedefed c) { std::cout << "sizeof(typedef,5):" << sizeof(c) << std::endl; } int main() { char a[5]; std::cout << "sizeof(local,5):" << sizeof(a) << std::endl; func(a); func2(a); func3(a); }
Result (yes it does compile even with the char[14] array being handed a char[5], segv surprise.. yummy!):
sizeof(local,5):5 sizeof(param,5):4 sizeof(param,14):4 sizeof(typedef,5):4
So whats going on.. well this is the unfortunate consequence a design decision in the Ansi C standard "6.2.2.1 Lvalues and function designators".
"Except when it is the operand of the sizeof operator or the unary & operator, or is a character string literal used to initialize an array of character type, or is a wide string literal used to initialize an array with element type compatible with wchar_t, an lvalue that has type ``array of type'' is converted to an expression that has type ``pointer to type'' that points to the initial element of the array and is not an lvalue. "
So to work around it your forced to take other measures. Generally I believe its a good idea to do it the right way first time and simply create a trivial struct for your primitive type, consider it a slightly bloated version of a typedef. Your alternatives to this are always passing a ref to the array, or always passing its size with it.
#include <iostream> void wasteful(char* c, std::size_t s) { std::cout << "sizeof(c):" << sizeof(c) << std::endl; std::cout << "sizeof(s):" << sizeof(s) << std::endl; std::cout << "wasted :" << sizeof(c) + sizeof(s) - s << std::endl; std::cout << "used :" << s << std::endl; } void easytoforget(char (&e)[5]) { std::cout << "sizeof(e):" << sizeof(e) << std::endl; }; struct Structed { Structed(char* a) { memcpy(a_,a,sizeof(a_)); } char a_[5]; }; void fixed(Structed e) { std::cout << "sizeof(e):" << sizeof(e) << std::endl; }; int main() { char a[5]; std::cout << std::endl << "Solutions:" << std::endl; wasteful(a, sizeof(a)); easytoforget(a); fixed(a); }