1、先谈优先级
最高级别 —— 有四个,他们并不像运算符:
[] | 数组下标 | 左到右结合 |
() | 用于(表达式) or 函数名(形参表) | 左到右结合 |
. | 读取结构体成员 | 左到右结合 |
-> | 读取结构体成员(通过指针) | 左到右结合 |
第二级别 —— 他们作用于单个变量 or 表达式:
* | 取址运算符,作用于指针 | 右到左结合 |
2、char *foo[]
数组下标优先级最高,结合方式“左到右”,因此等价于“char * (foo[])”。
问:int data[3];是什么意思?
答:定义了一个数组,大小是3,数组里存的是int 类型。
抽象一下,type data[x]; 定义了一个数组,大小是x,数组里存的是type类型。
∴ char * foo[3]; 定义了一个数组foo,大小是3,数组里存的是char *类型。
3、char (*foo)[]
我们已经知道char *foo[3]; 指的是一个大小为3的数组,数组存的是char *,通过foo[i]或*(foo + i)可以读取到对应为止的值。那如何理解:char (*foo) [3]?
取址运算符已经和foo优先结合了,foo一定是一个指针。这个指针指向一个地址,这个地址是1*3大小的数组 [char][char][char]。—— 指向数组的指针
char ch[3] = {'a', 'b', 'c'};
char (*foo)[3];
foo = &ch; // 合理
foo = ch; // 不合理,指向char的指针,不等于指向char数组的指针。
foo = &ch[0]; // 不合理,指向char的指针,不等于指向char数组的指针。
ch:指向数组首元素的指针
&ch:指向整个数组的指针。
对二者进行指针运算时,是不同操作。