关于int *p[n]和int (*p)[n]

本文通过具体示例详细解析了C语言中不同形式的指针声明及其意义,包括数组指针、指针数组及函数指针的区别,并介绍了如何通过理解运算符优先级来正确解读这些复杂的声明。


在编程中,会遇到这样的情况:int *p[n];
char (*p)[n];
还有一种情况是声明函数:
char *p();
char (*p)();
这些分别表示什么意思呢?


表面上看这些问题,好像是指针,但是,如何来正确判断这几个定义,需要我们首先有运算符优先级的概念。
  
在c语言中,[]和()的优先级比星号(星号的名字叫做“指针运算符”)要高,所以,在这几个声明中,先看[]和()。
同时,这两个括号的运算符的结合顺序,是从左到右的。因此,int *p[n],实际上相当与int *(p[n]),也就是(int *)(p[n])。
让我们来逐步分析:

int (*p)[n];
还有一种情况是声明函数:
int *p();
int (*p)();
这些分别表示什么意思呢?


表面上看这些问题,好像是指针,但是,如何来正确判断这几个定义,需要我们首先有运算符优先级的概念。
  
在c语言中,[]和()的优先级比星号(星号的名字叫做“指针运算符”)要高,所以,在这几个声明中,先看[]和()。
同时,这两个括号的运算符的结合顺序,是从左到右的。因此,int *p[n],实际上相当与int *(p[n]),也就是(int *)(p[n])。(在c专家编程中P215只有字符串常量才能初始化“指针数组”
让我们来逐步分析:

(int *)(p[n])首先是一个数组(比如,把int *换为int,就是“元素是整形数据的数组”。那么,换为int*,就是“元素是指向整形数据的指针的数组”)。

举个例子:

char *p[5];
*p[0]=“shit”;
*p[1]="ok";



再看另一个:
int (*p)[n]改变了自然的运算符的优先级,相当于(int)((*p)[n])。一有指针就头疼,我们把指针先替换掉,就是int a[n],是一个n维数组,数组首地址(也就是数组名)是a。
那么,int (*p)[n]也是一个n维数组,但是这个数组的首地址是*p,也就是说,p指向的内容,是一个数组的首地址。
那么,p就是指向一个数组的指针,这个数组中的元素都是int。实际上,p相当于是一个二维指针。


同样的道理,可以分析 int *p();和int (*p)();

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
注意,这里我们对于星号赋予了不同的含义。阐述如下:
int a;
int *p=&a;//定义指向a的指针p
*p = 10;

这里,第二行中的星号表示“定义了一个指向int型数据的指针,为什么呢?因为实际上,*  相当于  (int *),定义了一个指向int型数据的指针。
第三行的星号,表示p所指向的数据,因为星号前面并没有诸如int void char等表示类型的东西。

换句话说,如果星号前面有表示类型的int,void等数据,我们认为,这里的星号的意义,是“定义了一个指针”
如果星号前面没有表示类型的东西,那么我们认为,这里的星号的意义,是”该指针所指向的数据“。

那么,让我们回头看看int *p[n]和int (*p)[n]。
由于我们刚刚把优先级分析过,那么前者相当于(int *)(p[n]),后者相当于 int ((*p)[n])
根据刚才我们的关于星号的结论,前者表示定义了一个长度为n的数组(p[n]),每个元素都是指向int数据的指针(int *)。
后者表示,定义了一个int a[n]。这里大家都明白,然后把a换成*p,于是意思就是,p是一个指针,其指向的内容(也就是*p)是一个数组的首地址(就是a)
### 指针声明中星号位置的区别 在 C/C++ 中,指针声明时星号的位置(如 `int *p` `int* p`)并不会影响编译器对代码的理解,因为这两种写法在语法上是等价的。然而,从代码可读性风格的角度来看,它们存在一些细微的差异。 #### 1. **语法上的等价性** 无论星号靠近类型还是变量名,编译器都会将其解析为一个指向 `int` 类型的指针变量。例如: ```c int *p; int* q; ``` 上述两行代码在编译时完全等价,`p` `q` 都是指向 `int` 类型的指针[^1]。 #### 2. **星号靠近类型的情况 (`int* p`)** 当星号靠近类型时,表示该声明的重点在于“`int*` 是一种类型”,即 `p` 是一个属于 `int*` 类型的变量。这种写法通常用于强调指针本身是一种独立的数据类型。例如: ```c int* p, q; ``` 在这种情况下,`p` 是一个指向 `int` 的指针,而 `q` 是一个普通的 `int` 变量。这是因为 `int*` 被视为一种类型,而 `q` 并没有被声明为指针[^3]。 #### 3. **星号靠近变量名的情况 (`int *p`)** 当星号靠近变量名时,表示该声明的重点在于“`p` 是一个指针”,而不是将 `int*` 视为一种独立的类型。这种写法更符合传统的 C 风格,并且在声明多个变量时更容易理解。例如: ```c int *p, *q, r; ``` 在这种情况下,`p` `q` 是指向 `int` 的指针,而 `r` 是一个普通的 `int` 变量。这种方式明确地表明只有带星号的变量才是指针[^4]。 #### 4. **代码风格的选择** - 如果团队或项目倾向于将指针视为一种独立类型,则可以选择 `int* p` 的写法。 - 如果更注重单个变量的含义以及避免歧义,则可以选择 `int *p` 的写法。 #### 5. **实际应用中的建议** 为了提高代码的可读性,尤其是在声明多个变量时,推荐使用 `int *p` 的形式,因为它可以更清晰地表达每个变量的类型。例如: ```c int *p, a, *q; // 这里 p q 是指针,a 是普通变量 ``` 如果选择 `int* p` 的形式,则需要特别注意避免误解: ```c int* p, a, q; // 这里只有 p 是指针,a q 是普通变量 ``` ### 示例代码 以下是一个对比两种写法的示例: ```c #include <stdio.h> int main() { int a = 10, b = 20; // 星号靠近变量名 int *p = &a, *q = &b; printf("p = %d, q = %d\n", *p, *q); // 星号靠近类型 int* r = &a, s = 30, *t = &b; printf("r = %d, s = %d, t = %d\n", *r, s, *t); return 0; } ``` #### 输出结果 ``` p = 10, q = 20 r = 10, s = 30, t = 20 ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值