新浪博客

C语言中的指针概念和运算符优先级

2013-07-09 21:37阅读:
查看原文:http://blog.xieyc.com/pointer-and-operator-precedence-in-c-programming-language/
因为现在都用C#、Java一类的类型安全的语言了,关于最基本的C语言中和指针相关的几个概念,每次看懂之后,过一段总是又忘了……这次记下来:

一、关于 int* p 和 int *p 的区别:

上述两种形式在使用上没区别,当使用 int* p,q 和 int *p,q 的时候才会体现出区别。(牢记这一点有利于理解下文的内容,我个人习惯前一种写法,比较方便理解。)
注意:这两种形式不涉及间址运算符*在结合性上的优先级(完全由space决定)。

二、涉及数组 int *p[n] 和 int (*p)[n] 等:

1. int *p[n]
由于 [] 优先级比 * 高,因此 p 先与 [] 结合,将其理解为 int* p[n] 更容易,即 p 是一维数组名,数组 p[n] 的元素类型为 int*(指向int对象的指针)。举一例:
[code language='csharp']
int a=b=c=0;
int *p[3]={ &a, &b, &c };
[/code]

2. int (*p)[n]

由于p先与*结合,声明p为一指针,其指向一个int[n],即具有n个int元素的一维数组。
数组名的实质是指针,因此指针p也可以当做二维数组名处理,等效于int p[][n]。考虑以下代码:
[code language='csharp']
int a[2][3] = { {1,2,3}, {4,5,6} };
int (*p)[3];
p = a;
[/code]
注意到p+1指向二维数组的下一行,即{4,5,6},可以这样定义一个指针来指向一个二维数组。这里p与a不同的是:p是指针,可以移动(如p++),但是a是数组名,相当于符号常量,不能移动。
3. 数据类型 int(*)[n] 和 int*[n]
int(*)[n]为上述第2种定义中p的数据类型,先说明其是一个指针,指向 int[n];同理,可以有 int*[n] 类型,显然定义了一个数组(名),数组元素为int*,即上述第1中定义中p的数据类型。
从这里可以看出,这两种数据类型本质上是一致的,均为指针类型,所指对象是一个指向int元素的指针。因此上述定义1和定义2从本质上讲也是一致的,其区别类似于指针类型和数组名的区别(如能否移动等)。

三、函数指针 int *p() 与 int (*p)() 等:

1. int *p() 与上述类似,p先与()结合,可以理解为int* p(),即p是函数名,返回值是int*类型。
2. int (*p)()中,p是函数指针,指向一个返回值类型是int的函数,所指函数形参不确定。
3. int f()[] 试图声明一个返回值为数组int[]的函数f()。由于数组不能够作为函数返回值,声明不合法!
4. int f[]() 试图声明一维数组f[],数组成员是返回值为int的函数。该声明不合法,因为函数(不是函数指针)不能作为数组元素。函数(体)具有不同size,怎么能构成数组呢?
5. int (*f[])() 是合法声明,f先与[]结合,数组f[]中的元素是函数指针,所指函数的返回值为int。

附:C语言运算符优先级

优先级
运算符
名称或含义
使用形式
结合方向
说明
1
[]
数组下标
数组名[常量表达式]
左到右
()
圆括号
(表达式)/函数名(形参表)
.
成员选择(对象)
对象.成员名
->
成员选择(指针)
对象指针->成员名
2
-
负号运算符
-表达式
右到左
单目运算符
(类型)
强制类型转换
(数据类型)表达式
++
自增运算符
++变量名/变量名++
单目运算符
--
自减运算符
--变量名/变量名--
单目运算符
*
取值运算符
*指针变量
单目运算符
&
取地址运算符
&变量名
单目运算符
!
逻辑非运算符
!表达式
单目运算符
~
按位取反运算符
~表达式
单目运算符
sizeof
长度运算符
sizeof(表达式)
3
/

表达式/表达式
左到右
双目运算符
*

表达式*表达式
双目运算符
%
余数(取模)
整型表达式/整型表达式
双目运算符
4
+

表达式+表达式
左到右
双目运算符
-

表达式-表达式
双目运算符
5
<<
左移
变量<<表达式
左到右
双目运算符
>>
右移
变量>>表达式
双目运算符
6
>
大于
表达式>表达式
左到右
双目运算符
>=
大于等于
表达式>=表达式
双目运算符
<
小于
表达式<表达式
双目运算符
<=
小于等于
表达式<=表达式
双目运算符
7
==
等于
表达式==表达式
左到右
双目运算符
!=
不等于
表达式!= 表达式
双目运算符
8
&
按位与
表达式&表达式
左到右
双目运算符
9
^
按位异或
表达式^表达式
左到右
双目运算符
10
|
按位或
表达式|表达式
左到右
双目运算符
11
&&
逻辑与
表达式&&表达式
左到右
双目运算符
12
||
逻辑或
表达式||表达式
左到右
双目运算符
13
?:
条件运算符
表达式1? 表达式2: 表达式3
右到左
三目运算符
14
=
赋值运算符
变量=表达式
右到左
/=
除后赋值
变量/=表达式
*=
乘后赋值
变量*=表达式
%=
取模后赋值
变量%=表达式
+=
加后赋值
变量+=表达式
-=
减后赋值
变量-=表达式
<<=
左移后赋值
变量<<=表达式
>>=
右移后赋值
变量>>=表达式
&=
按位与后赋值
变量&=表达式
^=
按位异或后赋值
变量^=表达式
|=
按位或后赋值
变量|=表达式
15
,
逗号运算符
表达式,表达式,…
左到右
从左向右顺序运算

我的更多文章

下载客户端阅读体验更佳

APP专享