TearSnow Fan


C语言中的几个难懂的指针概念讨论(附运算符优先级)

因为现在都用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对象的指针)。举一例:

<br />int a=b=c=0;
int *p[3]={ &amp;a, &amp;b, &amp;c };<br />

2. int (*p)[n]

由于p先与*结合,声明p为一指针,其指向一个int[n],即具有n个int元素的一维数组。

数组名的实质是指针,因此指针p也可以当做二维数组名处理,等效于int p[][n]。考虑以下代码:

int a[2][3] = { {1,2,3}, {4,5,6} };
int (*p)[3];
p = a;

注意到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

,

逗号运算符

表达式,表达式,…

左到右

从左向右顺序运算

 

C语言运算符的“优先级口诀”

括号成员第一;    //括号运算符[]() 成员运算符. ->

全体单目第二;    //所有的单目运算符比如++ -- +(正) -(负) 指针运算*&

乘除余三,加减四;    //这个"余"是指取余运算即%

移位五,关系六;    //移位运算符:<< >> ,关系:> < >= <= 等

等于(与)不等排第七;    //即== !=

位与异或和位或;    //这几个都是位运算: 位与(&)异或(^)位或(|)

"三分天下"八九十;

逻辑或跟与;    //逻辑运算符:|| 和 &&

十二和十一;    //注意顺序:优先级(||) 底于 优先级(&&)

条件高于赋值,    //三目运算符优先级排到 13 位只比赋值运算符和","高//需要注意的是赋值运算符很多!

逗号运算级最低!    //逗号运算符优先级最低

本文固定链接: http://blog.xieyc.com/pointer-and-operator-precedence-in-c-programming-language/ | 小谢的小站

该日志由 xieyc 于2013年07月09日发表在 编程 分类下, 你可以发表评论,并在保留原文地址及作者的情况下引用到你的网站或博客。
原创文章转载请注明: C语言中的几个难懂的指针概念讨论(附运算符优先级) | 小谢的小站
关键字: , ,

C语言中的几个难懂的指针概念讨论(附运算符优先级):等您坐沙发呢!

发表评论

:wink: :neutral: :mad: :twisted: :smile: :shock: :sad: :roll: :oops: :eek: :mrgreen: :lol: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!:

快捷键:Ctrl+Enter