Cannot convert from 'T[N][2]' to 'T[][2]'
I have an API taking some options:
void init_api(const char* options[][2]);
I am allowed to pass a NULL pointer for no options, alternatively, an options array such as this can be passed:
const char* some_options[][2] = { {"opt1", "val1"},
开发者_运维百科 {"opt2", "val2"},
{0,0}
};
This works without problems:
...
init_api(some_options);
... or ...
init_api(NULL);
...
However, this fails to compile:
const char* my_options[][2] = NULL; // error C2440: 'initializing' : cannot convert from 'int' to 'const char *[][2]'
if(...) {
my_options = some_options; // error C2440: '=' : cannot convert from 'const char *[4][2]' to 'const char *[][2]'
}
init_api(my_options); // no error here
What is going on here? Can someone explain this?
To declare an empty array of array of pointers to const char, you should use:
const char* my_options[][2] = {};
You need to declare a pointer to an array of pointers to const char instead. I recommend using a typedef to simplify the syntax.
typedef const char* array_of_two_cstring[2];
array_of_two_cstring* my_options = NULL;
if (...) {
my_options = some_options;
}
init_api(my_options);
In C++ (it is herited from C), array can be implicitly converted to pointer (only once though, that is char[]
is compatible with char*
but char[][]
is compatible with char*[]
but not `char**). However, the variable cannot be reassigned. So here you need to use a pointer instead of an array.
The init_api
option accepts NULL
as a parameter because for the compiler, its prototype is void init_api(char const* (*)[2])
(the first array degenerated into a pointer), and NULL
is a valid pointer.
The compiler must know the array size.
If you omit the size of the array (ie: using []
) you need to initialize the array with the definition, in order to let the compiler count how many items that array will contain.
Moreover you are assigning a pointer (NULL
) to an array: const char *x[][2]
is an array of two pointers to const char
.
Edit:
In C++ (as in C), arrays can decay into pointers when you use them (with three exceptions which are not interesting here).
When you pass an array to a function expecting an array, what happens is that you actually pass a pointer to the array, since the array decays; you cannot pass an array by value in C or C++.
For this reason you can pass NULL
to your function; the function parameter will be NULL
, and if you try to access the array within your function (options[0]
) your application will crash: you'll be dereferencing an invalid pointer.
You cannot however set your array variable to NULL
, since it's not a pointer, it's an array: it will only decay when you'll use it in an expression.
const char* options[][2]
is an array of const char* pointers. You can't assign a pointer to an array.
A parameter declared as being an array of type T[N]
or T[]
becomes actually a parameter of type T*
. Same is done for functions (a parameter declared as R(Params)
becomes actually a parameter of type R(*)(Params...)
).
Such transformation however is not done for other declarations. The reason it's done for function by-value parameters is that there is no way in C to actually copy an array directly (that is, to actually copy its contents) and it doesn't make sense to try and copy a function either, so such parameters are transformed in a way that conveys their purpose in a meaningful way.
So while you are initializing a pointer in the function parameter case, you are trying to initialize an array in the other case.
精彩评论