多维数组的理解(可能导致“致命错误”)
/*
*C语言中只有“数组的数组”,即“一维数组”,并称为“多维数组”。
*/
以char szArr[][4][3];为例
该多维数组应该这样理解:
(1)一维数组szArr[]的单元为一个char[4][3]的二维数组;(同理,szArr[][4]的单元为一个char[3]的一维数组)
(2)当“数组名单独”出现的时候,“编译器”将其解释为“指向该‘一维数组’第一个元素”的“指针”;(所以,有时候我们会以为szArr[]的单元是一个二维指针,但可惜,事实并非如此)
(3)在函数传参的时候,数组名被“编译器”解释为“指向该‘一维数组’第一个元素”的“指针”;
(4)牢记一点:指针和数组名存在根本的不同。常见的例子是:
一个文件中定义int mango[100];//数组“开辟空间的特殊声明”,数组声明,意味mango[0]将“mango对应的符号表地址”+“偏移量”,之后访问内存单元
而另一个文件中声明extern int *mango;//指针的声明,意味着mango[0]将“mango对应的符号表地址”的内容取出后+“偏移量”,之后访问内存单元
当我们在另一个文件中mango[0];来使用时会出现程序的崩溃。
by the way:
(1)char str[][9] = {"hello", "world", "!"};
(str+1)//str的性质是char**指针,“+1”就是移动“char*”即一个字符串的大小,但类型还是char**,可以(atr+1)[1][1];来使用
(str[2])//str[2]的性质是字符串元素“!”
(&str+1)//移动单元为char的三维数组即{“hello”, "world", "!"}的下一个单元首地址
(*(str+1))//即“world”
(*(*(str+1)+1))//即‘o’,即str[1][1],又即(str+1)[0][1]
(2)见代码:
1 char s[][6] = {"hello", "world", "!"}; 2 char (*p)[6] = s; 3 char *pS[3] = {"hello", "world", "!"}; 4 char **pP = (char**)pS;//指向s就错了 5 6 printf("%c\n", s[2][0]); 7 printf("%c\n", pS[2][0]); 8 printf("%c\n", *(*(pS+2)));//完全同上,由编译器处理的 9 printf("%c\n", *(*(pP+2)));//完全同pP[2][0]; 10 printf("%c\n", p[2][0]); 11 printf("%c\n", *(*(p+2)));//完全同上
1 printf("%c\n", *(*(pP+2)));//VC上正确 2 printf("%c\n", pP[2][0]); 3 printf("%c\n", (*(pP+2))[0]); 4 printf("%c\n", *(pP[2]));
总结:
*见到a[i][j]的时候,a可能有四种定义方式;
*a[i][j]编译器会处理成(*(*(a+i)+j)),但是“不同的表达式”会被解释成不同的“执行方式”!!!所以,访问方式并不重要,不必在意这里。“重点”放在:小心地定义并初始化他们。
出处:《c专家编程》第4章、第9章
浙公网安备 33010602011771号