作者简介
高明亮,山东临朐人,2013年毕业于四川大学通信与信息系统专业,获工学博士学位。现任山东理工大学电气与电子工程学院副教授,硕士生导师。主要从事计算机视觉、深度学习方面的研究工作。主讲高级程序设计语言、数字图像处理技术、信息论与编码等课程。
内容简介
"2.4 指针
2.4.1 内存和地址
可以将计算机中的内存比作一栋楼房,每间房屋能够存储数据,并由房间号确定
标识。而计算机中的内存由数亿个位组成,一位能存储值0 和1,但是一位表示的范
围有限,所以单独谈一位没有实际意义。一般来讲,使用多个位为一组构成一个单位,
就可以存储较大范围的值。每一个单位为一个字节,它包含存储一个字符需要的位数。
在目前的许多计算机中,一个字节由8 个位构成,能存储无符号值0~255。
为了存储更大的值,我们把两个或多个字节合在一起,作为一个更大的内存单位。
例如:许多计算机以字节为单位存储整数,每个字一般由2 个或4 个字节组成,即常
用的int 等类型。假如记住一个值的存储地址,就可以按照此地址取得一个值。
2.4.2 指针变量
指针是一个数据在内存中的地址,指针变量就是存放地址的变量。在C 语言中,
指针变量是保存变量的地址,我们可以访问指针变量保存的地址值。指针变量的值为
数据的地址,包括数组、字符串、函数、普通变量等。
例如:在一个char 类型的变量a 中,存储一个字符a,其ASCII 码为65,占用
地址为0X11A 的内存。除此之外,还存在另一个指针变量p,其值也是0X11A。这
种情况就称p 指向a,也可以说p 为指针变量a 的指针。
1. 定义指针变量
定义指针变量和定义普通变量大致相同,都是变量名前面加星号(*),格式如下:
datatype *name;
或者
datatype *name=value; // 这里的“*”表示指针变量,“datatype”表示该指
针所指向的数据类型,value 为变量的地址值,通常情况下用取地址符获取变量地址
int a=10;
int *p_a=&a;
“p_a”是一个指向int 类型的指针变量,在定义指针变量“p_a”的同时对它进行
初始化,并将变量“a”的地址赋予它,此时“p_a”就指向了“a”。值得注意的是,“a”
前面必须要加取地址符(&),否则是错误的。
指针变量也可以连续定义,例如:
int *a,*b,*c; //a、b、c 的类型都是int*
第2 章 数据类型、运算符和表达式
2. 通过指针变量取得数据
指针变量存储了数据的地址,通过指针变量能够获得该地址的数据,格式为:
*pointer;
此处的“*”为指针运算符,用来取得某个地址上的数据,如例2.13 所示。
【例2.13】利用指针输出a 的值。
相应代码如下:
#include
int main()
{
int a=5;
int *p=&a;
printf (""%d,%d\n"",a,*p); // 两种方法都输出a 的数值
return 0;
}
程序运行结果为:
5, 5
知识点拨:假设“a”的地址是“0X1111”,“p”指向“a”后,“p”本身的值变
为“0X1111”。“*p”表示获取地址“0X1111”的数据,即变量“a”的值。从运行结
果看,“*p”和“&a”是等价的。
【例2.14】通过指针交换两个变量a、b 的值。
相应代码如下:
#include
int main()
{
int a=1,b=10,temp;
int *pa=&a,*pb=&b;
printf (""a=%d,b=%d\n"",a,b);
temp=*pa; // 将a 的值先保存起来
*pa=*pb; // 将b 的值交给a,将保存起来的a 值交换给b
*pb=temp; // 将保存起来的a 值交换给b,结束交换
printf (""a=%d,b=%d\n"",a,b);
return 0;
}
程序运行结果为:
a=1, b=10
a=10, b=1
知识点拨:通过运行结果可以看出,a、b 的值已经发生了交换。需要注意的是
临时变量“temp”的使用,执行“*pa=*pb;”语句后,“a”的值会被“b”的值覆盖。
因此,如果不预先将“a”的值保存起来,之后“a”的值就会被覆盖。
3. 一维数组和指针
从本质上来说,一维数组元素也是一个变量,也有自己的地址,因此完全可以定
义指向一维数组元素的指针。
例如:
int a[10],*p,*q;
p=&a[0];
q=&a[3];
以下语句定义了一个指向一维数组的指针变量:
int a[10],*p;
p=a;
注意:在C 语言中,数组名即为数组的首地址。此外,在一个一维数组中,无论
一个元素占用多少内存,如果一个指针“p”指向一维数组中的一个元素,那“p+1”
总会指向数组中的下一个元素。
【例2.15】指针加减整数。
相应代码如下:
#include
int main()
{
int a[10],*p=&a[5]; // 定义数组,命名指针变量
printf (""p=%p\n"",p);
printf (""p+1=%p\n"",p+1); // 对p 进行加操作
printf (""p-1=%p\n"",p-1); // 对p 进行减操作
return 0;
}
程序运行结果为:
p=0019FF1C
p+1=0019FF20
p-1=0019FF18
知识点拨:例2.15 中的程序定义了长度为10 的数组,然后命名了指针变量“*p”。
对“p”进行加减操作,实际上改变了地址值。如果“a”是一个一维数组,那么“a+i”
就是数组元素“a[i]”的地址(等价于“&a[i]”),而“a+i”就代表数组元素“a[i]”。
如果“a”是一个一维数组,而指针变量“p”指向“a[0]”,那么“p+i”就是数组元素“a[i]”的地址,而“*(p+i)”就代表数组元素“a[i]”。
【例2.16】键盘输入10 个数并逆序输出。
相应代码如下:
#include
int main()
{
int a[10],*p=a,i; // 初始化数组
printf ("" 输入10 个数: "");
for(i=0;i<10;i++)
scanf (""%d"",p+i); // 等价于scanf (""%d"",&a[i])
printf ("" 逆序后: "");
for(i=9;i>=0;i--)
printf(""%2ld "",*(p+i)); // 等价于printf (""%d"",a[i])
return 0;
}
程序运行结果为:
输入10 个数: 1 2 3 4 5 6 7 8 9 0
逆序后: 0 9 8 7 6 5 4 3 2 1
知识点拨:在例2.16 的程序中,为了访问不同的数组元素,改变的不是指针变
量“p”的值,而是整型变量“i”的值。虽然“p”是一个指针变量而不是一个数组,
但是C 语言允许将指针形式的“*(p+i)”表示为数组元素形式的“p[i]”,从而允许数
组指针“p+i”表示为“&p[i]”。
4. 指针变量作为函数参数
在C 语言中,函数的参数不限于整型、实型或字符型等数据类型,也可以是指针
类型。指针类型的函数参数意义为:将主调函数中的变量地址传递到被调函数中,从
而实现变量的函数间接引用。
【例2.17】利用函数交换a、b 的值。
相应代码如下:
#include
void swap(int *m,int *n) // 定义交换函数
{
int temp;
temp=*m; // 等价于temp=m;
*m=*n; // 等价于m=n;
*n=temp; // 等价于n=temp;
}
int main()
{
int a,b;
printf ("" 输入两个整数: "");
scanf(""%d%d"",&a,&b);
printf ("" 交换前: a=%d,b=%d\n"",a,b);
swap(&a,&b);
printf ("" 交换后: a=%d,b=%d\n"",a,b); // 输出交换后的值
return 0;
}
程序运行结果为:
输入两个整数:
3 5
交换前: a=3, b=5
交换后: a=5, b=3
知识点拨:在例2.17 的程序中,首先将主调函数中的局部变量的地址传递到被
调函数中,之后在被调函数中对主调函数中的局部变量进行间接引用,这在实质上是
一种跨函数的间接引用。关于函数的具体介绍参见第4 章。
2.4.3 动态内存的分配和管理
1. malloc 函数
函数声明:void *malloc(size_t Size)
所在文件:stdlib.h
参数:size_t Size(Size 表示要申请的字节数)
返回值:void *( 成功则返回“指向申请空间的指针”,失败则返回NULL)
函数功能:申请Size 个字节的堆内存并返回内存空间首地址
malloc 函数根据参数指定的尺寸来分配内存块,并且返回一个void 型指针,指
向新分配的内存块的初始位置。如果内存分配失败(内存不足),则函数返回NULL。
如分配100 个int 类型的空间:
int* p=(int *) malloc ( sizeof (int) * 100 );
2. free 函数
函数声明:void f ree(void *p)
所在文件:stdlib.h
参数:void *p( 指向堆内申请的合法空间)
返回值:void
功能:释放手动申请的堆内合法内存空间
例如:
int* p=(int *) malloc(4);
*p=100;
f ree(p); // 释放 p 所指的内存空间
以下是关于malloc 和free 的使用例子:
#include ""stdio.h""
#include ""stdlib.h""
#def ine SIZE 3
int main()
{
int *pt=NULL;
// 使用malloc() 申请空间
pt=(int*)malloc(SIZE * sizeof (int));
// 判断是否申请成功,若申请失败,则提示退出
if (pt==NULL)
{
printf ("" 内存未申请成功"");
return 0;
}
for (int i=0; i < SIZE; i++)
{
pt[i]=i; // 给申请的空间赋值
}
for (int i=0; i < SIZE; i++)
{
printf(""%d\n"", pt[i]); // 输出值
}
f ree(pt); // 使用f ree 释放空间
return 0;
}
程序运行结果为:
012
知识点拨:在该程序中,先定义了一个int 型的指针变量“pt”,然后通过malloc
函数申请空间容纳3 个int 型数据的内存,并将内存地址反馈给“pt”。通常,在动态
创建内存时需要对申请的内存进行判断,查看是否申请成功。如果没有申请成功,会
给出提示,并结束程序。如果已经申请成功,通过循环语句(第3.4 节)对指针变量
指向的数据逐个赋值。最后,释放“pt”指向的内存空间,程序结束。
值得一提的是,C++ 同样保留了malloc、free 函数,而且提供了更强大的运算符
new 和delete。关于new 和delete 运算符的使用请见第6.6 节。
2.5 基本运算符和表达式
运算符类似于数学计算中的加、减、乘、除等运算符号,用于变量(对象)之间
进行计算或比较。参与其中的对象叫作运算对象,一个或多个运算对象构成了表达式。
运算符可以沟通不同的运算对象,进而构成更加复杂的表达式,参与更加复杂的计算。
C 语言中有大量的运算符,可以满足不同的计算需求。
一般情况下,可以将表达式看作是运算符和操作数的有效组合。C 语言中有大量
的运算符组合,其中包括算数运算符、关系运算符和逻辑运算符等,与之对应的表达
式就叫作算数表达式、关系表达式、逻辑表达式等。在C 语言中,任何一个用于计
算值的公式都可以称为表达式。
2.5.1 赋值运算符和表达式
赋值号(=)是一个运算符,称为赋值运算符,由赋值运算符组成的表达式为赋
值表达式。其形式如下:
变量名= 表达式
赋值运算符(=)的左侧只能为变量,常量或表达式不能出现在赋值运算符的左侧,
因为不符合语法规则。赋值运算符的意义不同于数学中的“=”,左侧变量得到的值即
为赋值表达式的值。
复合赋值运算符有“+=”“-=”“*=”“/=”“%=”。复合赋值运算符与赋值运算符的优先级相同,例如“n+=3”的运算规则等同于“n=n+3”。
2.5.2 算术运算符和表达式
算术运算符主要有7 个,其中2 个为一元运算符(“+”“-”),5 个为二元运算符(“+”“-”“*”“/”“%”)。一元运算符“+”“-”的作用是对数据取正号和负号,如“int a=+5”“int b=-5”;二元运算符“+”“-”“*”“/”“%”分别用于两个对象的加、减、乘、除和取余运算。
【例2.18】通过本例熟悉运算符的使用。
相应代码如下:
#include
#include
int main()
{
int a=3;
int b=6;
int c=2;
int d1, d2, d3, d4;
d1=(a+b)*c/a;
d2=a+b*c/a;
d3=a/c;
d4=a%c;
printf (""d1=%d\n"",d1);
printf (""d2=%d\n"",d2);
printf (""d3=%d\n"",d3);
printf (""d4=%d\n"",d4);
return 0;
}
程序运行结果为:
d1=6
d2=7
d3=1
d4=1
知识点拨:在C 语言中,算数运算符存在严格的优先级,类似于数学四则运算中
的乘法、除法优先于加法、减法。在C 语言中,算数运算符和圆括号的优先级的高低
次序为:“( )”>“+”(单目)>“-”(单目)>“*”>“/”>“+”>“-”(关于运算
符优先级详细介绍请见第2.6 节的内容)。只有单目运算符“+”“-”的结合性是从
右到左的,其余运算符的结合性都是从左到右的,例如“(a+b)*c/a”的结果为6,而
“d2=a+b*c/a”的结果为7。“a/c”结果为1.5,但是d3 类型为int 型,因此,结果为1。a 对c 取余的结果为1,因此,“a%c=1”。
2.5.3 关系运算符和表达式
关系运算符都是双目运算符,其结合性均为左结合。关系运算符的优先级低于算
术运算符,高于赋值运算符。在6 个关系运算符中,“<”“<=”“>”“>=”的优先级相同,高于“==”和“!=”,“==”和“!=”的优先级相同。
由关系运算符组成的式子为关系表达式,如“a>b”即为关系表达式。在C 语言中,
同逻辑表达式一样,关系表达式的值也为逻辑值,即布尔型(bool),取值为真或假。
注意:在C 语言中,“==”表示等于,而“=”表示赋值。如果要做判断,需要
使用“==”。
如语句:
if (a==1)
{…}
表示判断是否满足条件“a==1”,如果满足则进行{} 中的处理,是典型的判断语
句。但是,如果写成:
if (a=1)
{…}
则表示给“a”赋值为1。程序将不做判断,直接进行“{}”中的处理。初学C++ 时,
很容易混淆“==”和“=”,大家需要格外注意。
2.5.4 逻辑运算符和表达式
逻辑运算符主要有3 种:并且、或者和相反。
(1)并且:逻辑为与,操作符为“&&”,表示两者都成立。
(2)或者:逻辑为或,操作符为“||”,表示只要两个其中的一个条件成立即可。
(3)相反:逻辑为非,操作符为“!”,表示(如果)之前成立,现在就不成立;(如果)在之前不成立,那么现在就成立。
逻辑表达式的值与关系表达式的值一样,结果成立为1,不成立为0。在C 程序
里面,用0 表示不成立,用除0 之外的任何数表示成立。
逻辑运算符的优先级为“!”>“ &&”>“ ||”。
2.5.5 位运算符和表达式
位运算符主要有6 种:按位与(&)、按位或(|)、异或(^)、取反(~)、右移(>>)、左移(<<)。
1. 按位与运算符
按位与运算符(&)进行的是这样的算法:0&0=0,0&1=0,1&0=0,1&1=1。
【例2.19】利用按位与运算符输出结果。
相应代码如下:
#include
int main()
{
int a=4;
int b=5;
printf(""%d"",a&b);
}
程序运行结果为:
4
知识点拨:a=4 的二进制表示a=(0100)2,b=5 的二进制表示b=(0101)2,a&b=(0100)2,换算成十进制数为4。
2. 按位或运算符
按位或运算符(|)进行的是这样的算法:0|0=0,0|1=1,1|0=1,1|1=1。
【例2.20】利用按位或运算符输出结果。
相应代码如下:
#include
int main()
{
int a=060;
int b=017;
printf (""%d"",a|b);
}
程序运行结果为:
63
知识点拨:在C 语言中,如果一个整型是以0 开头的,那么它就是一个八进制数。
如果是以0x 开头的,那么它就是一个十六进制数。此处的a 和b 都是八进制数。如
果换算成二级制数a=(0110000)2, b=(0001111)2。a|b=(0111111)2,换算成十进制数为
63。
3. 异或运算符
异或运算符(^)进行的是这样的算法:0^0=0,0^1=1,1^0=1,1^1=0(相同为0,
不同为1)。
【例2.21】利用异或运算符输出结果。
相应代码如下:
#include
int main()
{
int a=3;
int b=4;
a=a^b;
b=b^a;
a=a^b;
printf (""a=%d b=%d"",a,b);
}
程序运行结果为:
a=4 b=3
知识点拨:a=(3)10=(011)2,b=(4)10=(100)2。a=a^b=(111)2,b=b^a=(011)2=(3)10。a=a^b=(100)2=(4)10。故最终结果:a=4,b=3。
4. 取反运算符
取反运算符(~)是一元运算符,作用是对整数的二进制码进行取反,具体操作
是将二进制位上的0 和1 互换值。例如:对10101 进行取反后的结果为01010。
【例2.22】利用取反运算符输出结果。
相应代码如下:
#include
int main()
{
int a=5;
printf (""%d\n"",~a);
}
程序运行结果为:
-64
分析:如果计算机是64 位,则描述八进制的a 时需要用到64 位,即a=(077)8
=(0… 0111111)2,~a=(1… 1000000)2。
其符号位(最左一位)是1,表明它表示的是负数,欲求其源码,须先对其取反,
然后再加1:(0… 0111111)2+(0… 1)2=(0… 1000000)2,最后在得到的源码前加
一个负号,即-(0… 1000000)2=-(64)10。
5. 右移运算符
右移运算符(>>)的作用是对一个数的二进制位进行右移,右移的位数由操作数
决定,且为非负值,舍弃移动右端的低位。若a=15,即(00001111)2,右移2 位,
得数为(00000011)2。
6. 左移运算符
左移运算符(<<)的作用是对一个数的二进制位进行左移,左移的位数由操作数
决定,且为非负值,高位溢出则舍弃移动左端的高位。例如:将a 的二进制数左移2
位,右边空出的位补0,左边溢出的位舍弃。若a=15,即(00001111)2,左移2 位,
得(00111100)2。
【例2.23】利用右移运算符输出结果。
相应代码如下:
#include
int main()
{
int a=17;
int b=a>>1;
int c=a<<1;
printf (""b=%d\n"",b);
printf (""c=%d\n"",c);
}
程序运行结果为:
b=8
c=34
知识点拨:a=(17)10=(10001)2, b=a>>1=(1000)2=(8)10, c=a<<1=(100010)2=(34)10。
2.5.6 条件运算符和表达式
条件运算符也称为三目运算符,其一般格式为:
表达式1? 表达式2: 表达式3;
执行过程为:先对表达式1 进行计算,若其计算结果为真,则进行下一步,再对
表达式2 进行计算,将计算结果作为整个条件表达式的值。若表达式1 计算结果为假,
则对表达式3 进行计算,将计算结果作为整个条件表达式的值。需要注意的是,条件
运算符的优先级很低,其结合性为从右向左。
【例2.24】利用条件运算符输出结果。
相应代码如下:
#include
int main()
{
int a,b,max;
scanf (""%d,%d"",&a,&b);
max=(a>b)?a:b;
printf (""%d"",max);
}
程序运行结果为:
1, 2(输入)
2
2.5.7 逗号运算符和表达式
逗号运算符(,)是C 语言中一种特殊的运算符。用“,”将表达式连接起来的式
子称为逗号表达式,其一般格式为:
表达式1, 表达式2,…, 表达式n;
逗号运算符的结合性为从左到右,因此,逗号表达式为从左到右进行运算。先计
算表达式1,再计算表达式2,依次进行,最后计算表达式n。最后一个表达式的值
就是此逗号表达式的值,如“i=2,i++,i+5;”这个逗号表达式的值为8,i=3。在所有
的运算符中,逗号运算符的优先级最低。
2.5.8 指针运算符和表达式
当程序中已具有一个指针,并且希望获取它所引用的对象时,可以使用间接运算
符(*)。该运算符有时也被称为“解引用运算符”。它的操作对象必须是指针类型。
如果“ptr”是指针,那么“*ptr”就是“ptr”所指向的对象或函数;如果“ptr”
是一个对象指针,那么“*ptr”就是一个左值,可以把它当作赋值运算符左边的操作数。
【例2.25】利用指针运算符输出结果。
相应代码如下:
#include
#include
int main()
{
f loat a,*ptr=&a;
*ptr=1.5; // 将1.5 赋值给变量a
++(*ptr); // 将变量a 的值自加
printf (""%f "" ,a);
}
程序运行结果为:
2.500000
知识点拨:“*ptr=1.5”是将1.5 赋值给变量“a”,“++(*ptr)”是将变量“a”的值加1。
在这个示例最后的语句中,“ptr”的值保持不变,但“a”的值变成2.5。如果指针操作数的值不是某个对象或函数的地址,则间接运算符的操作结果无法确定。像其他一元操作数一样,运算符“&”和“*”具有很高的优先级,操作数的组合方式是从右到左。因此,表达式“++(*ptr)”中的括号是没有必要的。
运算符“&”和“*”是互补的:如果“x”是一个表达式,用于指定一个对象或
一个函数,那么表达式“*&x”就等于“x”。相反,在形如“&*pt”的表达式中,这
些运算符会互相抵消,表达式的类型与值等效于“ptr”。
2.5.9 地址运算符和表达式
“&”是一元运算符,可以返回操作数的内存地址。如果操作数x 的类型为T,则
表达式“&x”的类型是T 类型指针(指向T 的指针)。
对地址运算符进行操作时,要保证其操作数可以在内存中找到其地址。当需要初
始化指针,以指向某些对象或函数时,需要获得这些对象或函数的地址。
【例2.26】利用地址运算符输出结果。
相应代码如下:
#include
int main()
{
int *ptr,a=15;
ptr=&a;
printf (""%d"",*ptr);
}
程序运行结果为:
15
知识点拨:其中“ptr=&a”是正确的,这便使指针“ptr”指向“a”,而“ptr=&(a+1)”
是错误的,因为“a+1”不是一个左值。
2.5.10 求字节运算符和表达式
“sizeof ”是C 语言中的一种单目运算符,并不是函数。sizeof 运算符的功能是返回指定的数据类型或表达式的值在内存中占用的字节数。操作数可以是一个表达式或
类型名,操作数的存储空间大小由操作数的类型决定。一般int 型变量是4 个字节,
double 型为8 个字节。
【例2.27】利用字节运算符输出结果。
相应代码如下:
#include
int main()
{
int a;
double b;
a=sizeof (a);
b=sizeof (b);
printf(""a=%d,b=%f"" ,a,b);
}
程序运行结果为:
a=4, b=8.000000
2.5.11 强制运算符和表达式
强制类型转换是指把变量从一种类型转换为另一种数据类型。比如:为了把long
类型的值存储到简单整型中,可以对long 型进行强制转换,使其转换为int 型。进行
强制转换时就必须用到强制转换运算符,在使用强制类型转换符时,会把一个整数变
量转换为另一个浮点变量,最终得到一个浮点数。
【例2.28】利用强制运算符输出结果。
相应代码如下:
#include
int main()
{
int sum=18, count=5;
double x;
x=(double) sum / count;
printf (""%f \n"", x );
}
程序运行结果为:
3.600000
2.5.12 下标运算符和表达式
下标运算符([])通常用于访问数组元素。借助于下标运算符可以获取数组中单
独的元素。下标运算符需要两个操作数。在最简单的情况下,一个操作数是一个数组
名称,而另一个操作数是一个整数。
如“array”是一个数组的名称。“array[0]”表示数组“array”的第1 个元素(数
组的首元素从索引0 开始),“array[9]”表示数组“array”的第10 个元素。
2.5.13 自增与自减运算符和表达式
自增运算符(++)和自减运算符(--)的作用是对运算对象进行“+1”或“-1”
的操作,如“i++”意为“i=i+1”。其中运算符“++”为单目运算符,运算对象包括
实型变量和整型变量,不能为常量或表达式,所以像“1++”这类表达式是不合法的。
使用这两种运算符构成表达式时,前缀与后缀形式均可,即“i++”或“++i”都是合
法的,且效果相同,但作为表达式会计算出不同的值,如例2.29 和例2.30 所示。
【例2.29】利用自增运算符“i++”输出结果。
相应代码如下:
#include
int main()
{
int i=1,j;
j=i++;
printf (""j=%d,i=%d"",j,i);
}
程序运行结果为:
j=1, i=2
【例2.30】利用自增运算符“++i”输出结果。
相应代码如下:
#include
int main()
{
int i=1,j;
j=++i;
printf (""j=%d,i=%d"",j,i);
}
程序运行结果为:
j=2, i=2
知识点拨:例2.29 中的语“j=i++;”,表示先将i 的值赋给j 之后,再对i 进行自加。因此,j 的值为i 自加之前的结果,即j=1,i=2。例2.30 中,语句“j=++i;”,
表示先将i 自加,然后将自加后的结果赋值给j,故j 的值为 i 自加之后的结果,即
j=2,i=2。
关于自增与自减运算符的重载,将会在9.4 节进一步学习。
2.6 运算符的优先级和结合性
在前面的介绍中,提到了运算符的优先级问题。在一个表达式中,其数据对象会
有多个不同的运算符连接,且具有不同的数据类型,在此表达式中也会有多种不同的
运算。如果不统一运算顺序,得出的结果就会多种多样,所以,规定运算的优先级是
非常有必要的。只有这样,才能保证运算结果的合理性、准确性,以及唯一性。
表达式的结合次序由运算符的优先级决定,优先级高的运算符先进行结合,同一
行运算符优先级相同。
例如:
k=(j>i) && (8==i)
根据优先级的高低,完全可以写成:
k=j>i && 8==i
但第一种写法在实际操作中是比较提倡的,由于括号运算符优先级最高,所以程
序运行时出错率更低。
C++ 运算符的优先级和结合性见表2-4。
表2-4 C++运算符的优先级和结合性
运算符 优先级 结合性
[]、()、.、-> 1 自左到右
-(负号运算符)(类型)、
++、--、*(取值运算符)、
&(取地址运算符)、
!、~、sizeof
2 自右到左
/、*、% 3 自左到右
+、- 4 自左到右
<<、>> 5 自左到右
>、>=、<、<= 6 自左到右
==、!= 7 自左到右
& 8 自左到右
^ 9 自左到右
| 10 自左到右
&& 11 自左到右
|| 12 自左到右
?: 13 自右到左
=、/=、*=、%=、+=、-=、<<=、>>=、&=、^=、|= 14 自右到左
, 15 自左到右
本章习题
1. 判断题:
(1)在C 语言中,不允许类型不同的数据之间进行运算。( )
(2)一个变量被定义后,它的数据类型就确定了,无法进行改变了。( )
(3)在C 语言中,数值型数据都可以进行% 运算。( )
(4)在C 语言中,一个变量可以同时被定义为多个类型。( )
(5)在C 语言中,变量可以不经过定义直接使用。( )
(6)在程序中,temp 和TEMP 是两个不同的变量。( )
2. 编程题:
(1)键盘录入一个整数,求它的平方和、平方根,保留两位小数。
(2)编写程序将“Helloworld”改写为密文,密文要求使用原字母后面的第二个
字母代替原字母,如“a->c”。
(3)编写程序,由控制台输入10 个整数,将它们排序后输出(由小到大)。
(4)编写函数,使函数实现以下要求:键盘录入3 个值,将它们排序后输出(由
大到小)。
(5)编写程序,打印九九乘法表。"
"培养编程思维,轻松玩转C++!
内容全面:内容全面,讲解细致,循序渐进,便于理解
视频讲解:扫码观看,通俗易懂,知识拓展,随时随地
轻松上手:大量示例,边学边练,轻松学习,快速提升"




