无法将char*[2]类型的数组地址传递给char***函数

bwo*_*ebi 9 c arrays pointers parameter-passing pass-by-reference

我的XCode(默认编译器应该是clang?)向我展示了这段代码的警告:

Incompatible pointer types passing 'char *(*)[2]' to parameter of type 'char ***' (当调用func时)

void func (char ***arrayref, register size_t size) {
    /// ...
}

int main()
{
    char *array[2] = {"string", "value"};
    func(&array, 2);
}
Run Code Online (Sandbox Code Playgroud)

而这段代码没问题(=没有警告):

void func (char **arrayref, register size_t size) {
    /// ...
}

int main()
{
    char *array[2] = {"string", "value"};
    func(array, 2);
}
Run Code Online (Sandbox Code Playgroud)

虽然这消除了警告

func((char***)&array, 2);
Run Code Online (Sandbox Code Playgroud)

我仍然不知道为什么第一个发出警告,而后者不发出警告.

另外,当第一个出现问题时,我也希望第一个发出警告,如:

Incompatible pointer types passing 'char *[2]' to parameter of type 'char **'

Joh*_*ode 15

Time for a brief refresher on array semantics.

Except when it is the operand of the sizeof or unary & operators, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element in the array.

The expression array in your code has type "2-element array of char *", or char *[2]. When you pass it as an argument to func, as in

func( array, 2 );
Run Code Online (Sandbox Code Playgroud)

表达式转换为"指向char *" 的类型的表达式,或者char **,这是函数期望的类型,表达式的值是第一个元素的地址:array == &array[0].这就是为什么你没有得到第二个代码片段的警告.

在第一个片段中,数组是一元运算&符的操作数,因此不会发生到指针类型的转换; 相反,表达式的类型是"指向2元素数组的 指针char *",或者char *(*)[2]与之不兼容char **.地址是相同的(数组的第一个元素的地址与数组本身的地址相同),但类型不匹配,因此警告.

那为什么这很重要?指针只是一个地址,所有地址都是一样的,对吧?好吧,不.指针是地址的抽象,具有相关的类型语义.指向不同类型的指针不必具有相同的大小或表示,指针算法取决于指向类型的类型.

例如,如果我将指针声明为char **p;,则表达式p++将使指针前进指向下一个类型对象char *,或指向sizeof (char *)当前地址的字节.如果p被声明为char *(*p)[2],然而,表达p++将前进p至点到下一个二单元阵列char *,其值为2*sizeof (char *)从当前地址字节.


glg*_*lgl 5

char *array[2] = {"string", "value"};
Run Code Online (Sandbox Code Playgroud)

是一个包含2个元素的数组char *.

使用array地址作为指向第一个元素的指针,即类型char **.

&array结果用于指向同一位置但指向类型的指针char *(*)[2](不确定拼写是否正确).

这与a不同char ***- 内存中的表示完全不同.

为了更加冗长,

+++++++++++++++++++++++
+ array[0] + array[1] +
+++++++++++++++++++++++
Run Code Online (Sandbox Code Playgroud)

这是阵列.

char ** p1 = array; // is a pointer to the first element, which in turn is a pointer.
char *(*p2)[2] = &array; // is a pointer to the whole array. Same address, but different type, i. e. sizeof(*p1) != sizeof(*p2) and other differences.

char ***p3 = &p1; // Now, p1 is a different pointer variable which has an address itself which has type `char ***`.
Run Code Online (Sandbox Code Playgroud)