参考书《C Primer Plus》第六版10.数组和指针10.1.1 数组的初始化数组完全不初始化其元素的值是随机数。数组只初始化部分元素未初始化的元素会被初始化为0。数组初始化列表元素个数超出数组类型元素个数有的编译会报错有的编译器只会警告忽略初始化列表中多出的元素。int test1[3];printf(“test1[0] %d, test1[1] %d, test1[2] %d\n”, test1[0], test1[1], test1[2]); //未初始化就使用编译器会警告int a[3] {0}; //这行代码的意思是把数组的第一个元素a[0]初始化为0其它未初始化的元素会被编译器自动初始化为0。int test2[3][2] {(1,2), (3,4), (5,6)}; //test2[0] {2, 4}, test2[1] {6, 0}, test2[2] {0, 0}编译器会警告int *pData test2[0];printf(“test2[0][0] %d, test2[0][1] %d\n”, pData[0], pData[1]); //输出为test2[0][0] 2, test2[0][1] 4pData test2[1];printf(“test2[1][0] %d, test2[1][1] %d\n”, pData[0], pData[1]); //输出为test2[1][0] 6, test2[1][1] 0pData test2[2];printf(“test2[2][0] %d, test2[2][1] %d\n”, pData[0], pData[1]); //输出为test2[2][0] 0, test2[2][1] 0int test3[3] {1, 2, 3, 4, 5};printf(“test3[0] %d, test3[1] %d, test3[2] %d\n”, test3[0], test3[1], test3[2]);10.1.2 数组索引数组索引必须是整数可以为负数。数组索引为正数表示从前往后数索引为负数表示从后往前数。array[-1] (char *)array sizeof(array) - 1;char name[4] {‘K’, ‘A’, ‘N’, ‘G’};char *pByte name 1;printf(“BYTE %c\n”, pByte[-1]); //输出为BYTE KpByte (char *)name 1;printf(“BYTE %c\n”, pByte[-1]); //输出为BYTE KpByte name 1; //编译可通过但有警告指针类型不匹配name的类型为char (*)[4]printf(“BYTE %c\n”, pByte[-1]); //输出为BYTE GpByte (char *)(name 1);printf(“BYTE %c\n”, pByte[-1]); //输出为BYTE G10.6 数组和指针的异同数组和指针只是访问数据的方式相同本质上是不同的东西不能当做同一个东西。*是数组和指针的解引用操作[]是数组和指针的索引操作。1数组和指针的共同点访问数据的方式相同数组和指针都可以通过解引用形式*(xi)和索引形式x[i]访问数据。数组可以通过类似指针的解引用形式*(ai)访问。指针可以通过类似数组的索引形式p[i]访问。2数组和指针的差异本质上是不同的东西数组首地址所在的存储单元中存储的是数据内容。指针所在的存储单元中存储的是数据的地址。数组名不能出现在左边即不能向数组名赋值因为数组首地址是固定的不能改变。10.7 指针和多维数组10.7.2 指针的兼容性嵌套指针赋值时把非const指针赋给const指针是不安全的会导致const失效int *p;const int **pp; //const修饰的是紧随其后的int即(**pp)pp p; //不会报错但是不安全会导致const失效const int n 8;*pp n; //*pp的值是p即p n间接把p指向了n*p 6; //通过p改变了只读变量n的值导致pp的const失效了10.7.3 函数和多维数组多维数组形参的函数多维数组形参必须指定最高阶之外的尾数。当一维数组作为函数参数时编译器会把数组解析为指向其首元素地址的指针维数信息会被忽略但是这条规则并不是递归的。当多维数组作为函数参数时编译器只会把数组的最高维解析为指向其首元素地址的指针低维保持不变。只有最高维的维数信息会被忽略低维的维数信息不会被忽略。只忽略最高维的维数不影响计算指针的步长若低维的维数也忽略指针的步长就无法计算了。void Func(int p[5])会被解析为 void Func(int *p);void Func(int *p[5])会被解析为 void Func(int **p);void Func(int p[4][5])会被解析为void Func(int p[][5])或void Func(int (*p)[5]);void Func(int p[4][5][6])会被解析为void Func(int p[][5][6])或void Func(int (*p)[5][6])10.8 函数指针10.8.1 函数指针的声明和定义typedef void (*fn_t)(void); 只定义函数指针的类型fn_t并不定义函数指针变量 fn_t func; 定义函数指针变量funcvoid (*func)(void); 声明函数指针类型的同时定义函数指针变量func10.8.2 函数指针的赋值和调用赋值func test; 或 func test; 函数名就是函数地址所以取地址符可以不加调用func(); 或(*func)();10.8.3 函数指针数组fn_t func[3]; 或 void (*func[3])(void);调用方式func[0]();func[3]是数组void (*)(void)是函数指针[]的优先级高于*所以func优先跟[]结合构成数组10.8.4 函数指针数组的指针fn_t (*func)[3];或void (*(*func)[3])(void);调用方式(*func)[2](); 或func[1][2]();(*func)[3]是数组func是指向数组的指针。指针func的步长是3个函数指针func的结果是func加12个字节。10.8.5 函数指针作为函数形参void test(fn_t func);或void test(void (*func)(void));10.8.6 指针和数组运算符的优先级[]优先级高于*char*p[5][]优先与p结合构成数组数组的元素是char *.优先级高于**p.data.优先与data结合构成结构成员取值结果是*(p.data)()优先级高于*char *fn()fn优先与()构成函数声明声明的是函数不是函数指针所以fn是函数不是函数指针。