《C语言运算符的优先级》由会员分享,可在线阅读,更多相关《C语言运算符的优先级(14页珍藏版)》请在金锄头文库上搜索。
1、优先级运算符 名称或含义()-(类型)+数组下标圆括号成员选择(对象)成员选择(指针)负号运算符强制类型转换自增运算符自减运算符sizeof运算符及其优先级使用形式结合方向数组名常量表达式(表达式)/函数名(形参表)对象成员名对象指针- 成员名-表达式(数据类型)表达式+变量名/变量名+变量名/变量名一取值运算符取地址运算符逻辑非运算符按位取反运算符长度运算符除乘余数(取模)加左移右移*指针变量&变量名!表达式表达式sizeo f(表达式)表达式/表达式表达式*表达式整型表达式/整型表达式表达式+表达式表达式-表达式变量表达式变量表达式大于表达式表达式=大于等于表达式 =表达式小于表达式表达式
2、=小于等于表达式 =表达式左到右优先级运算符名称或含义使用形式结合方向7=等于表达式=表达式左到右!=不等于表达式!=表达式8&按位与表达式&表达式左到右9按位异或表达式表达式左到右10|按位或表达式I表达式左到右11&逻辑与表达式&表达式左到右12|逻辑或表达式|表达式左到右13?:条件运算符表达式1?表达式2:表达式3右到左14=赋值运算符变量=表达式右到左/=除后赋值变量/=表达式*=乘后赋值变量*=表达式%=取模后赋值变量%=表达式+=加后赋值变量+=表达式二减后赋值变量-=表达式=右移后赋值变量=表达式&二按位与后赋值变量&=表达式=按位异或后赋值变量=表达式|=按位或后赋值变量匸表
3、达式15逗号运算符表达式,表达式,左到右左到右右到左左到右左到右左到右数组和指针一、指向一维数组元素的指针int a10, *p;p=&a0; /* 与语句 p=a; 等价 */此时p指向数组中的第0号元素,即a0, *p就是*a,就是a0的值,*(a+i)就是ai的值。由于数组元素在 内存中是连续存放的,根据地址运算规则,p+i和a+i都表示为ai的地址(即&ai)。二、二维数组元素的地址为了说明问题,我们定义以下二维数组:int a34 = 0,l,2,3, 4,5,6,7, 8, 9,10,11;二维数a也可这样来理解:数组a由三个元素组成:a0,a1,a2,而每个元素又是一个一维数组,
4、且都含 有4个元素(相当于4列)。如图所示:a | a0 | | 0 | 1 | 2 | 3 | (0x1000)|_|_|_|_| a1 | | 4 | 5 | 6 | 7 | (0x1010)| |_|_|_|_| a2 | | 8 | 9 | 10| 11| (0x1020)但从二维数组的角度来看,a代表二维数组的首地址,当然也可看成是二维数组第0行的首地址,a+1就代表第 1行的首地址,依次。如果此二维数组的首地址为0x1000,由于第0行有4个整型元素,所以a+1为0x1010。既然我们把a0,a1,a2看成是一维数组名,可以认为它们分别代表它们所对应的数组的首地址,也就是 讲a0代
5、表第0行中第0列元素的地址,即&a00,a1是第1行中第0列元素的地址,即&a10,根据地址 运算规则,a0+1即代表第0行第1列元素的地址,即&a01, 般而言,ai+j即代表第i行第j列元素的地 址,即&aij。另外,在二维数组中我们还可用指针的形式来表示各元素的地址,如a0与*(a+0)等价,ai与*(a+i)等价, 它表示数组元素ai的地址&ai0。而二维数组元素aij可表示成*(ai+j)或*(*(a+i)+j),或者写成(*(a+i)j。三、指向一个由n个元素所组成的数组指针数组指针用的比较少,但在处理二维数组时,还是很方便的。例如:int (*p)4;/* 在数组指针的定义中,圆
6、括号是不能少的,否则它是指针数组 */int a34;p=a;开始时p指向二维数组第0行,当进行p+1运算时,根据地址运算规则,此时放大因子为4x4=16,所以此时正 好指向二维数组的第 1 行。和二维数组元素地址计算的规则一样, *p+1 指向 a01, *(p+i)+j 则指向数组元素 aij。四、指针数组因为指针是变量,因此可设想用指向同一数据类型的指针来构成一个数组,这就是指针数组。数组中的每个元素 都是指针变量,根据数组的定义,指针数组中每个元素都为指向同一数据类型的指针。格式: 类型标识 *数组名整型常量表达式;例如: int *a10;以上指针数组中包含10个指针变量a0,a1,
7、a2,.,a9,可以指向10个不同的地址。指针函数和函数指针一、指针函数指针函数是指声明其返回值为一个指针的函数,实际上就是返回一个地址给调用函数。格式: 类型说明符 *函数名(参数)例如: void *GetDate(int ID);二、函数指针指向函数的指针包含了函数的地址,可以通过它来调用函数。格式: 类型说明符 (*函数名)(参数)例如: int (*fptr)(int ID);其实这里不能称为函数名,应该叫做指针的变量名。这个特殊的指针指向一个返回整型值的函数。指针的声明笔 削和它指向函数的声明保持一致。指针名和指针运算符外面的括号改变了默认的运算符优先级。如果没有圆括号,就 变成了
8、一个返回整型指针的函数的原型声明。可以采用下面的形式定义函数指针数据类型:typedef int (*T_MY_FUNC)(int ID);/* 此时” T_MY_FUNC fpt r;等价于 ” in t (*fp tr )(in t ID);” */可以采用下面的形式把函数的地址赋值给函数指针:fptr二&Function;/* 或用 “fptr二Function; */可以采用下面的形式通过指针来调用函数:(*fptr)(ID); /*或用“fptr(ID); ”的格式,使用这种调用格式看上去与调用普通函数无异,因此使 用前一种调用格式可以明确指出是通过指针而非函数名来调用函数的。*/三
9、、指针的指针指针的指针用于指向指针的地址,它的声明有两个星号。例如:char *cp; 如果有三个星号,那就是指针的指针的指针,有四个星号那就是指针的指针的指针的指针,依次类推。四、指向指针数组的指针指针的指针另一用法是处理指针数组。有些程序员喜欢用指针数组来代替多维数组,一个常见的用法就是处理 字符串。char *Names=Bill,c Sam,丁Jim, 0;main()char *nm=Names; /* 定义一个指向指针数组的指针的指针 */ while(*nm!=0) printf(%sn,*nm+);可变参数的函数下面是一个简单的可变参数的函数,该函数至少有一个整数参数,第二个参
10、数也是整数,是可选的。#include stdarg.hvoid simple_va_fun(int i,.)va_list arg_ptr;int j = 0;va_start(arg_ptr, i);/* va 在这里是可变参数(variable-argument)的意思 */j=va_arg(arg_ptr, int);va_end(arg_ptr);pri ntf (%d %dn, i, j);return;从这个函数的实现可以看到,使用可变参数应该有以下步骤:1) #includest darg.h2) 在函数里定义一个va_list型的变量,这里是arg_ptr,这个变量是指向参数
11、的指针。3) 用va_start宏初始化变量arg_ptr,该宏的第二个参数是第一个可变参数的前一参数,是一固定的参数。4) 用va_arg返回可变的参数,并赋值给j。va_arg的第二个参数是要返回的参数的类型,这里是int型。5) 最后用va_end宏结束可变参数的获取。下面的例子可以进一步加深对可变参数的理解,该函数的效果与sprintf函数完全相同:void my_printf(char *buffer, const char *format,.)va_list arg_ptr;va_start(arg_ptr, format);vspri ntf (buffer, forma t,
12、arg_p tr); /* 将 arg_p tr 按 forma t 格式打印到 buffer 中 */ va_end(arg_ptr);位域的使用位域的定义和位域变量的说明与结构定义相仿,其形式例如为:struct bsint a:8;int b:2;int :2/* 无位域名,该 2bit 不能使用 */int c:4; 对于位域的定义尚有以下几点说明:1. 一个位域必须存储在同一个字节中,不能跨两个字节。如一个字节所剩空间不够存放另一位域时,应从下一 单元起存放该位域。也可以有意使某位域从下一单元开始。2. 由于位域不允许跨两个字节,因此位域的长度不能大于一个字节的长度,也就是说不能超过
13、8 位二进位。3. 位域可以无位域名,这时它只用来作填充或调整位置。无名的位域是不能使用的。链表typedef struct studentint number;int score;struct student *next; STUDENT_LINK;/*建立一个有 cnt 个结点的链表,返回链表头*/ STUDENT_LINK *link_creat(int cnt)STUDENT_LINK *head = NULL; /* head 始终指向链表头,用于返回 */ STUDENT_LINK *new_node; /* new_node 始终指向新申请的节点 */STUDENT_LINK *cur_node; /* cur_node 始终指向当前操作的(也是最后的)节点 */ int n = 1;while (n = cnt)printf(您正在创建节点%d: n, n);new_node = (STUDENT_LINK *)malloc(sizeof(STUDENT_LINK); link_input(new_node);if (n = 1) /*