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)
第一个工作,但第二个不工作.我不明白为什么会这样.
问题是,当我们这样做时&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 **.
但是,array是char [10]和&array是char (*)[10]不是char **.
因此,当你&array作为一个参数传递时,char (*)[10]就像一个char *传递作为参数的行为,如上所述.
因此,**(char **) &bla == 'j'虽然*(char *) &array == 'j'.做一些简单的实验,你会证明它.
你正在void *elemAddr投入char **并试图尊重它.这只适用于&bla它char **.&array将导致段错误,因为"john"被解释为演员的地址.
C 规范规定 array 和 &array 是相同的指针地址。
\n\n将数组传递给函数时使用数组名称会根据 C 规范自动将参数转换为指针(重点是我的)。
\n\n\n\n\n6.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
因此调用 func(array) 将导致将指向 char[] 的指针传递给函数。但在数组上使用取址运算符有一种特殊情况。由于数组具有“类型数组”类型,因此它属于规范的“其他”类别(强调我的)。
\n\n\n\n\n6.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
因此,调用 func(&array) 仍然会导致将单个指针传递给函数,就像调用 func(array) 一样,因为 array 和 &array 都是相同的指针值。
\n\n常识会让您相信 &array 是指向数组第一个元素的双指针,因为使用 & 运算符通常会产生这种行为。但数组不同。因此,当您将传递的数组指针作为指向数组的双指针取消引用时,您会遇到分段错误。
\n