引用Array与对数组指针的引用

Ioa*_*dze 14 c arrays pointers

void check(void* elemAddr){
    char* word = *((char**)elemAddr);
    printf("word is %s\n",word);
}

int main(){
    char array[10] = {'j','o','h','n'};
    char * bla = array;
    check(&bla);
    check(&array);
}
Run Code Online (Sandbox Code Playgroud)

输出:

word is john

RUN FINISHED; Segmentation fault; core dumped;
Run Code Online (Sandbox Code Playgroud)

第一个工作,但第二个不工作.我不明白为什么会这样.

Sta*_*ant 7

问题是,当我们这样做时&array,我们得到的char (*)[10]是一个char [10]而不是一个char **.

在我们进行实验之前,我要强调的是,当我们将数组作为参数传递给函数时,C实际上将数组转换为指针.不会复制大量数据.

因此,int main(int argc, char **argv)int main(int argc, char *argv[])C中的相同.

这使我们可以用简单的方式打印数组的地址printf.

我们来做实验:

char array[] = "john";
printf("array:  %p\n", array);
printf("&array: %p\n", &array);

// Output:
array:  0x7fff924eaae0
&array: 0x7fff924eaae0
Run Code Online (Sandbox Code Playgroud)

知道这一点后,让我们深入研究你的代码:

char array[10] = "john";
char *bla = array;
check(&bla);
check(&array);
Run Code Online (Sandbox Code Playgroud)

bla是的char *,&bla是的char **.

但是,arraychar [10]&arraychar (*)[10]不是char **.

因此,当你&array作为一个参数传递时,char (*)[10]就像一个char *传递作为参数的行为,如上所述.

因此,**(char **) &bla == 'j'虽然*(char *) &array == 'j'.做一些简单的实验,你会证明它.

你正在void *elemAddr投入char **并试图尊重它.这只适用于&blachar **.&array将导致段错误,因为"john"被解释为演员的地址.


T J*_*son 2

C 规范规定 array 和 &array 是相同的指针地址。

\n\n

将数组传递给函数时使用数组名称会根据 C 规范自动将参数转换为指针(重点是我的)。

\n\n
\n

6.3.2.1-4

\n\n

除非它是 sizeof 运算符或一元 &\n 运算符的操作数,或者是用于初始化数组的字符串文字,否则具有 \xe2\x80\x98\xe2\x80\x98array 类型的\n 表达式\xe2\x80\x99\xe2\x80\x99 被转换为\n 表达式,其类型为 \xe2\x80\x98\xe2\x80\x98 指向类型\xe2\x80\x99\xe2\x80\x99 的指针数组对象的初始\n 元素,并且不是左值。如果数组对象具有寄存器存储类,则行为未定义。

\n
\n\n

因此调用 func(array) 将导致将指向 char[] 的指针传递给函数。但在数组上使用取址运算符有一种特殊情况。由于数组具有“类型数组”类型,因此它属于规范的“其他”类别(强调我的)。

\n\n
\n

6.5.3.2-3

\n\n

一元 & 运算符产生其操作数的地址。如果操作数\n 的类型为 \xe2\x80\x98\xe2\x80\x98type\xe2\x80\x99\xe2\x80\x99,则结果的类型为 \xe2\x80\x98\xe2\x80\x98 的指针\xe2\x80\x99\xe2\x80\x99。如果操作数是一元 * 运算符的结果,则该运算符和 & 运算符都不会被求值,结果就像两者都被省略一样,除非运算符的约束仍然适用并且\n结果不是左值。类似地,如果操作数是 [] 运算符的结果,则 & 运算符和 [] 隐含的一元 * 都不会被求值,结果就像删除了 & 运算符并[] 运算符更改为 + 运算符。否则,结果是指向由其操作数指定的对象或函数的指针

\n
\n\n

因此,调用 func(&array) 仍然会导致将单个指针传递给函数,就像调用 func(array) 一样,因为 array 和 &array 都是相同的指针值。

\n\n

常识会让您相信 &array 是指向数组第一个元素的双指针,因为使用 & 运算符通常会产生这种行为。但数组不同。因此,当您将传递的数组指针作为指向数组的双指针取消引用时,您会遇到分段错误。

\n