谨记:

上帝在缔造每个人的时候,给予每个人的一切都是相同的,然而,人与人却是存在如此大的差距,记着上帝为你关上了一扇门,那么他一定会为你打开另一扇窗户,人与人之间的差距是会不断的缩小的,如果你连走出的勇气都没有,那么为你开再多窗户和门都是毫无意义,因为,你永远是在原地。努力就有收获,付出就有回报!

引言

和其他程序设计语言一样,C语言中表示运算的符号称为运算符。运算符是告诉编译程序执行特定算术或逻辑操作的符号,运算的对象称为操作数。

对一个操作数进行运算的运算符称为单目运算符,对两个操作数进行运算的运算符称为双目运算符,三目运算符对三个操作数进行运算。用运算符和括号可以将操作数连接起来组成表达式。

C语言提供了40多个运算符,其中一部分跟其他高级语言相同(例如“+”、“−”、“*”等运算符),另外的与汇编语言类似,对计算机的底层硬件(如指定的物理地址)能进行访问。如下图所示:

这篇文章,大概讲解算术运算符和表达式、关系运算符和表达式、逻辑运算符和表达式以及位运算符和表达式,望读者认真体会和学习。

1、算术运算符和表达式

1.1 算术运算符

算术运算符包括我们熟悉的数学课上讲的加减乘除四则运算和求模运算以及正负运算符。如下图:

程序案例:

int main(int argc, const char * argv[]) {

@autoreleasepool {

int a = 10, b = 20 ,c;

double x = 5, y = 15, z;

c = a + b;//c赋值为30;

c = a - b;//c赋值为 - 10;

c = a * b;//c赋值为 200;

c = a / b;//c赋值为 0;这里是求商

c = a % b;//c赋值为10;

printf("%d",c);

z = x + y;//z赋值20;

z = x - y;//z赋值-10;

z = x * y;//z赋值75;

z = x / y; //z赋值0.3333333

// z = x % y;报错是因为 % 运算符只针对整数。

}

return 0;

}

说明:

1、“+”、“−”、“”、“/”4种运算符的操作数,可以是任意基本数据类型,其中“+”、“−”、“”与一般算术运算规则相同。

2、除法运算符“/”包括了除和整除两种运算,当除数和被除数都是整型数时,结果只保留整数部分而自动舍弃小数部分,注意0不能作为除数。除数和被除数只要有一个浮点数,进行浮点数相除。

3、取模运算就是求余数,取模运算要求两个操作数只能是整数,不能是浮点数,如10.8%2或5%2.0都是不正确的。

4、运算符“−”除了用作减法运算符之外,还有另一种用法,即用作负号运算符。用作负号运算符时只要一个操作数,其运算结果是取操作数的负值。

5、字符型数会自动地转换成整型数, 因此字符型数也可以参加双目运算。

6、在进行 % 运算符操作时,如果被除数的绝对值小于除数的绝对值,那么结果就为被除数,的值,结果的符号取决于被除数,如果被除数是负数不管除数正负性,结果都为负,如果被除数为正,不管除数正负,结果都为正,例如:

int main(int argc, const char * argv[]) {

@autoreleasepool {

int a = 10,b = 20;

int c = a % b;

printf("%d\n",c);

int a1 = -10;

int c1 = a1 % b;

printf("%d\n",c1);

int b1 = -20;

int c11 = a % b1;

printf("%d\n",c11);

int c2 = a1 % b1;

printf("%d\n",c2);

int x = -40,y = 15,z;

z = x % y;

printf("%d\n",z);

}

return 0;

}

输出的结果为:

10

-10

10

-10

-10

Program ended with exit code: 0

1.2 算术表达式

算术表达式就是用算术运算符和括号可以将操作数连接起来组成算术表达式。

比如:a+2b-5、18/3(2.5+8)-'a'

在一个算术表达式中,我们允许出现不同类型的算术运算符,那么在这里,就有一个优先级的说法,在数学领域里,我们都知道一个表达式我们应该先算什么后算什么,在这里也是一样的。

1.2.1 优先级

C语言对每一种运算符都规定了优先级,混合运算中应按次序从高优先级的运算执行到低优先级的运算。算术运算符的优先级从高到低排列如下(自左向右)。

1.2.2 类型的转换

A、自动转换(隐式转换)自动转换是在源类型和目标类型兼容以及目标类型广于源类型时发生一个类型到另一类的转换。这种转换是系统自动进行的。其中,float型向double型的转换和char型向int型的转换是必定要进行的,即不管运算对象是否为不同的类型,这种转换都要进行。图4-1中纵向箭头表示当运算对象为不同类型时的转换方向。如int型与double型数据进行运算时,是先将int型转换为double型,再对double型数据进行运算,最后的运算结果也为double型。

B、强制转换 利用强制类型转换运算符可以将一个表达式的运算结果转换成所需要的类型。强制类型转换的一般形式是: (数据类型名)表达式

(int)a double(x + y);这里就不多做解释了。很简单的,读者可以自己尝试一哈。

int main(int argc, const char * argv[]) {

@autoreleasepool {

float a=2.34;

printf ("(int) a=%d, a=%f\n",(int)a,a);

return 0;

}

}

运行结果:(int) a=2

a=2.340000

Program ended with exit code: 0

2、关系运算符和表达式

2.1 关系运算符

在程序中经常需要通过比较两个值的大小关系来决定程序下一步的工作。比较两个值的运算符称为关系运算符。关系运算符对两个表达式进行比较,返回一个真/假值。在C语言中的关系运算符,如下图:

关系运算符都是双目运算符,其结合性均为左结合。即从左往右,关系运算符的优先级低于算术运算符,高于赋值运算符。

在这6个关系运算符中,“”、“>=”的优先级相同,高于“= =”和“!=”,“= =”和“!=”的优先级相同。根据优先级的关系,以下表达式具有等价的关系。

c>a+b 和 c>(a+b)

a>b==c 和 (a>b)==c

a=b>c 和 a=(b>c)

2.2 关系表达式

用关系运算符把表达式进行一个关联,则称为关系表达式。

一般格式: 表达式 关系运算符 表达式

关系表达式真值表: 真 和 假 程序中用 1 和 0代替。

int main(int argc, const char * argv[]) {

@autoreleasepool {

int a = 10, b = 15;

if (a > b) {

printf("true\n");

}else{

printf("false\n");

}

if (a % b > 0) {

printf("true %d \n ",(a % b));

}else{

printf("false\n");

}

}

return 0;

}

输出结果:false

true 10

Program ended with exit code: 0

在C99标准以前,C语言没有能表达true和false的类型,那个时候只能用“1”和“0”来代替,或者用宏定义另外,通过typedet来自定义bool类型,如下所示。

typedef unsigned char bool;

#define TRUE 1

#define FALSE 0

然而在C99标准,C语言给出了_Bool这个类型,这样我们在编写程序的时候,我们就可以直接使用true和false。

_Bool k = true;//C99标准

if (k) {

printf("true");

}

3、逻辑运算符和表达式

3.1 逻辑算法

在我们C语言中啊,给我们提供了3种逻辑运算符,即:&&(逻辑运算与)、||(逻辑运算或)、!(逻辑运算非),其中与运算符(&&)和或运算符(||)均为双目运算符,具有左结合性;非运算符(!)为单目运算符,具有右结合性。下面具体介绍这三种运算符。

A、逻辑运算与(&&)

真值表:

| 表达式1 | 表达式2 | &&值 |

|--------|--------|--------|

| 0 | 0 | 0 |

| 0 | 1 | 0 |

| 1 | 0 | 0 |

| 1 | 1 | 1 |

双目运算符,只有两个运算量都是1时,运算结果才为1。

B、逻辑运算或(||)

当两个运算量进行或运算时,只要有一个运算量为“1”,结果就为“1”,

| 表达式1 | 表达式2 | ||值 |

|--------|--------|--------|

| 0 | 0 | 0 |

| 0 | 1 | 1 |

| 1 | 0 | 1 |

| 1 | 1 | 1 |

C、逻辑非( !)

单目运算符,当运算量进行非运算,结果会取反。即 0 变为 1, 1 变为 0。

3.2 表达式

逻辑表达式的一般形式如下:

表达式 逻辑运算符 表达式

其中的表达式也可以是逻辑表达式,从而组成了嵌套的情形。如图,优先级。

通过优先级,我们可以得出:

a>b && c>d等价于(a>b) && (c>d)

!b==c||d

a+b>c && x+yc) && ((x+y)

逻辑表达式的值是式中各种逻辑运算的最后值,以“1”和“0”分别代表“真”和“假”。

在进行编程的时候,我们同样也可以用true和false进行一个运算。

int main(int argc, const char * argv[]) {

@autoreleasepool {

int a = 10,b = 20, c = 30;

if (a < b && b > c ) {

printf("true\n");

}else{

printf("false\n");

}

if (a > b || b < c) {

printf("true\n");

}else{

printf("false\n");

}

if (!(a == b)) {

printf("true\n");

}

}

return 0;

}

输出结果:

false

true

true

Program ended with exit code: 0

4、位运算符及表达式

4.1 位运算符

位运算符是指二进制位的运算,在C语言中,给我们提出了如下为运算符,

位与(&)

位或(|)

异或(^)

取反(~)

左移(<

右移(>>)

A、与运算符(&)

双目操作符,当两个位进行相与时,只有两者都为“1”时结果才为“1”,其他都为“0”。

如:0x8a & 0x45

0x8a 1000 1010

0x45 0100 0101

结果 0000 0000 转换为十六进制 0x00

0xff & 0xf3

0xff 1111 1111

0xf3 1111 0011

结果 1111 0011 转换为十六进制 0xf3

B、或运算符(|)

双目操作符,当两个位进行相或时,两者中只要有一方为“1”,结果就为“1”,其他都为0.

(1)注意:位或符号是一个|,两个||是逻辑或。

(2)真值表:1|0=1 1|1=1 0|0=0 0|1=1

(3)从真值表可以看出:位或操作的特点是:只有2个0相位或才能得到0,只要有1个1结果就一定是1.

(4)位或和逻辑或的区别:位或时两个操作数是按照二进制位彼次对应位相与的,逻辑或是两个操作数作为整体来相或的。

如: 0x2b | 0xf7

0x2b 0010 1011

0xf7 1111 0111

结果 1111 1111 转换为十六进制 0xff

C、位取反~

(1)注意:C语言中位取反是~,C语言中的逻辑取反是!

(2)按位取反是将操作数的二进制位逐个按位取反(1变成0,0变成1);而逻辑取反是真(在C语言中只要不是0的任何数都是真)变成假(在C语言中只有0表示假)、假变成真。

实验:任何非0的数被按逻辑取反再取反就会得到1;

任何非0的数被按位取反再取反就会得到他自己;

D、位异或^

(1)位异或真值表:1^1=0 0^0=0 1^0=1 0^1=1

(2)位异或的特点:2个数如果相等结果为0,不等结果为1。记忆方法:异或就是相异就或操作起来。

位与、位或、位异或的特点总结:

位与:(任何数,其实就是1或者0)与1位与无变化,与0位与变成0

位或:(任何数,其实就是1或者0)与1位或变成1,与0位或无变化

位异或:(任何数,其实就是1或者0)与1位异或会取反,与0位异或无变化

E、左移位<< 与右移位>>

C语言的移位要取决于数据类型。

对于无符号数,左移时右侧补0(相当于逻辑移位)

对于无符号数,右移时左侧补0(相当于逻辑移位)

对于有符号数,左移时右侧补0(叫算术移位,相当于逻辑移位)

对于有符号数,右移时左侧补符号位(如果正数就补0,负数就补1,叫算术移位)

嵌入式中研究的移位,以及使用的移位都是无符号数。

重点

特定位清零用&

(1)回顾上节讲的位与操作的特点:(任何数,其实就是1或者0)与1位与无变化,与0位与变成0

(2)如果希望将一个寄存器的某些特定位变成0而不影响其他位,可以构造一个合适的1和0组成的数和这个寄存器原来的值进行位与操作,就可以将特定位清零。

(3)举例:假设原来32位寄存器中的值为:0xAAAAAAAA,我们希望将bit8~bit15清零而其他位不变,可以将这个数与0xFFFF00FF进行位与即可。

4.2 表达式

4.2.1、特定位置1用|

(1)回顾上节讲的位或操作的特点:任何数,其实就是1或者0)与1位或变成1,与0位或无变化

(2)操作手法和刚才讲的位与是类似的。我们要构造这样一个数:要置1的特定位为1,其他位为0,然后将这个数与原来的数进行位或即可。

4.2.2、特定位取反用^

(1)回顾上节讲的位异或操作的特点:(任何数,其实就是1或者0)与1位异或会取反,与0位异或无变化

(2)操作手法和刚才讲的位与是类似的。我们要构造这样一个数:要取反的特定位为1,其他位为0,然后将这个数与原来的数进行位异或即可。

4.2.3.如何用位运算构建特定二进制数

4.2.3.1、寄存器位操作经常需要特定位给特定值

(1)从上节可知,对寄存器特定位进行置1或者清0或者取反,关键性的难点在于要事先构建一个特别的数,这个数和原来的值进行位与、位或、位异或等操作,即可达到我们对寄存器操作的要求。

(2)解法1:用工具软件或者计算器或者自己大脑计算,直接给出完整的32位特定数。

优势:可以完成工作,难度也不大,操作起来也不是太麻烦。

劣势:依赖工具,而且不直观,读程序的人不容易理解。

评价:凑活能用,但是不好用,应该被更好用的方法替代。

(2)解法2:自己写代码用位操作符号(主要是移位和位取反)来构建这个特定的二进制数

4.2.3.2、使用移位获取特定位为1的二进制数

(1)最简单的就是用移位来获取一个特定位为1的二进制数。譬如我们需要一个bit3~bit7为1(隐含意思就是其他位全部为0)的二进制数,可以这样:(0x1f<<3)

(2)更难一点的要求:获取bit3~bit7为1,同时bit23~bit25为1,其余位为0的数:((0x1f<<3) | (7<<23))

4.2.3.3、再结合位取反获取特定位为0的二进制数

(1)这次我们要获取bit4~bit10为0,其余位全部为1的数。怎么做?

(2)利用上面讲的方法就可以:(0xf<<0)|(0x1fffff<<11)

但是问题是:连续为1的位数太多了,这个数字本身就很难构造,所以这种方法的优势损失掉了。

(3)这种特定位(比较少)为0而其余位(大部分)为1的数,不适合用很多个连续1左移的方式来构造,适合左移加位取反的方式来构造。

(2)思路是:先试图构造出这个数的位相反数,再取反得到这个数。(譬如本例中要构造的数bit4~bit10为0其余位为1,那我们就先构造一个bit4~bit10为1,其余位为0的数,然后对这个数按位取反即可)

4.2.3.4、总结:位与、位或结合特定二进制数即可完成寄存器位操作需求

(1)如果你要的这个数比较少位为1,大部分位为0,则可以通过连续很多个1左移n位得到。

(2)如果你想要的数是比较少位为0,大部分位为1,则可以通过先构建其位反数,然后再位取反来得到。

(3)如果你想要的数中连续1(连续0)的部分不止1个,那么可以通过多段分别构造,然后再彼此位与即可。这时候因为参与位或运算的各个数为1的位是不重复的,所以这时候的位或其实相当于几个数的叠加。

4.2.4.位运算实战演练1

回顾:要置1用|,用清零用&,要取反用^,~和<< >>用来构建特定二进制数。

4.2.4.1、给定一个整型数a,设置a的bit3,保证其他位不变。

a = a | (1<<3) 或者 a |= (1<<3)

4.2.4.2、给定一个整形数a,设置a的bit3~bit7,保持其他位不变。

a = a | (0b11111<<3) 或者 a |= (0x1f<<3);

4.2.4.3、给定一个整型数a,清除a的bit15,保证其他位不变。

a = a & (~(1<<15)); 或者 a &= (~(1<<15));

4.2.4.4、给定一个整形数a,清除a的bit15~bit23,保持其他位不变。

a = a & (~(0x1ff<<15)); 或者 a &= (~(0x1ff<<15));

4.2.4.5、给定一个整形数a,取出a的bit3~bit8。

思路:

第一步:先将这个数bit3~bit8不变,其余位全部清零。

第二步,再将其右移3位得到结果。

第三步,想明白了上面的2步算法,再将其转为C语言实现即可。

a &= (0x3f<<3);

a >>= 3;

4.2.4.6、用C语言给一个寄存器的bit7~bit17赋值937(其余位不受影响)。

关键点:第一,不能影响其他位;第二,你并不知道原来bit7~bit17中装的值。

思路:第一步,先将bit7~bit17全部清零,当然不能影响其他位。

第二步,再将937写入bit7~bit17即可,当然不能影响其他位。

a &= ~(0x7ff<<7);

a |= (937<<7);

4.2.5.位运算实战演练2

4.2.4.7、用C语言将一个寄存器的bit7~bit17中的值加17(其余位不受影响)。

关键点:不知道原来的值是多少

思路:第一步,先读出原来bit7~bit17的值

第二步,给这个值加17

第三步,将bit7~bit17清零

第四步,将第二步算出来的值写入bit7~bit17

4.2.4.8、用C语言给一个寄存器的bit7~bit17赋值937,同时给bit21~bit25赋值17.

思路:4.2.4.6的升级版,两倍的4.2.4.6中的代码即可解决。

分析:这样做也可以,但是效果不够高,我们有更优的解法就是合两步为一步。

4.2.6.技术升级:用宏定义来完成位运算

4.2.6.1、直接用宏来置位、复位(最右边为第1位)。

#define SET_NTH_BIT(x, n) (x | ((1U)<

#define CLEAR_NTH_BIT(x, n) (x & ~((1U)<

4.2.6.2、截取变量的部分连续位。例如:变量0x88, 也就是10001000b,若截取第2~4位,则值为:100b = 4

#define GETBITS(x, n, m) ((x & ((0U)<> (n-1))

分析:这个题目相当于我们4.2.4.5中做的事情,只不过要用宏来实现。

这个题目相当于是要把x的bit(n-1)到bit(m-1)取出来

复杂宏怎么分析:

((x & ((0U)<> (n-1))

第一步,先分清楚这个复杂宏分为几部分:2部分

(x & ((0U)<> (n-1)

分析为什么要>>(n-1),相当于是我们4.2.4.5中的第二步

第二步,继续解析剩下的:又分为2部分

x & ((0U)<

分析为什么要&,相当于我们4.2.4.5中的第一步

第三步,继续分析剩下的:

~ (~(0U)<

这个分析时要搞清楚第2坨到底应该先左边取反再右边<

解法:第一,查C语言优先级表;第二,自己实际写个代码测试。

说明这个式子应该是 ((0U)<

10001000

00001110

00001000

c语言中1 2 3怎么运算符号,C语言运算符和表达式(一)相关推荐

  1. c语言的运算答案,C语言运算符与表达式的练习题答案.doc

    C语言运算符与表达式的练习题答案.doc C语言运算符与表达式的练习题单项选择题 1以下选项中,正确的 C 语言整型常量是( D ). A. 32L B. 510000 C. -1.00 D. 567 ...

  2. c语言求字符ascii,C语言中ASCII码是什么意思? c语言怎么求字符的ascii码

    导航:网站首页 > C语言中ASCII码是什么意思? c语言怎么求字符的ascii码 C语言中ASCII码是什么意思? c语言怎么求字符的ascii码 相关问题: 匿名网友: 是一个字符表,一个 ...

  3. c语言中char是多少字节,c语言中char_char c = \'\\1\' 十进制是多少_c语言char

    网友求助:c语言中char_char c = \"\\1\" 十进制是多少_c语言char 问题 最佳答案 推荐答案 char一般默认是1个字节的无符号整型,范围0~255.如果是 ...

  4. c语言while作用范围,c语言中while是什么意思啊? , c语言while循环的表达式

    导航:网站首页 > c语言中while是什么意思啊? , c语言while循环的表达式 c语言中while是什么意思啊? , c语言while循环的表达式 匿名网友: 事例程序:void mai ...

  5. c语言中atan2(a b)怎么运算,C语言中的atan和atan2(转)

    在C语言的math.h或C++中的cmath中有两个求反正切的函数atan(double x)与atan2(double y,double x)  他们返回的值是弧度 要转化为角度再自己处理下. 前者 ...

  6. 在c语言中a 这条语句的作用,C语言复习第二章

    C语言第二章 C语言复习(第二章) 一.填空 1.若采用十进制数的表示形式,则077为( ),0111为( ),0xab为( ). 2.C语言中的标识符只能由3种字符组成,它们是( ).( )和( ) ...

  7. c语言中b的作用是什么意思,C语言中是什么意思?ab怎么理解?

    C语言中&是什么意思?a&b怎么理解?以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! C语言中& ...

  8. c语言中的stdbool.h头文件,【C语言】中的stdbool.h头文件

    C语言中的stdbool.h头文件 一.相关基础知识 二.具体内容 Win7下安装的VS2015中的stdbool.h的位置为: F:\Program Files (x86)\Microsoft Vi ...

  9. c语言中aver是什么意思_嵌入式C语言基础编程—5年程序员给你讲函数,你真的懂函数吗?...

    本文主要讲述的内容: 1函数概述 2函数定义的一般形式 3函数的参数和函数的值 3.1形式参数和实际参数 3.2函数的返回值 4函数的调用 4.1函数调用的一般形式 4.2函数调用的方式 4.3被调用 ...

  10. C语言为运算表达式添加括号,读书笔记-c语言-运算符与表达式

    1.算术运算符:+-*/% %要求参与运算的两个量必须是整型或字符型的,实型(float,double等)的数据不能做%运算. 算术表达式 运算符和数据可以组成运算的式子,称为表达式.举例:10+20 ...

最新文章

  1. java两个线程同时运行_java如何几乎同时结束两个线程
  2. 面向过程(结构化)分析方法与面向对象分析方法的区别
  3. android:关于主工程和library project
  4. WindowsForm 计算器
  5. C#流对象使用完后不立即释放的问题
  6. 推荐给开发和设计人员的iPad应用
  7. re 模块 分组特别说明
  8. elementui下拉框选择图片_element ui下拉框如何实现默认选择?
  9. linux vim文本编辑器
  10. 洛谷 P2341 [HAOI2006]受欢迎的牛
  11. 【长篇连载】桌面管理演义 尾声
  12. VMWare安装Ubuntu 12.04开启虚拟机的Unity Mode模式
  13. git merge;fork同步集中库代码;a标签返回
  14. 剑指offer面试题64. 求1+2+…+n(逻辑符短路)(递归)
  15. 仿链家地图找房_iOS地图找房、周边(仿链家、安居客等地图找房)-高德地图-OC...
  16. ADC的指标详细定义,SNR,以下内容无关: -------------------------------------------分割线----------------SNDR,SFDR,THD等
  17. 2020年浙江大学金融考研经验分享
  18. Springboot使用POI读写excel(详细)
  19. 与、或、非、与非、或非、异或、同或
  20. 26.看前端视频的感悟,来自碎碎念记录

热门文章

  1. [IOS APP]毕淑敏经典有声小说
  2. Invalid use of SingleClientConnManager: connection still allocated解决方案
  3. IEEE 2021年新增Fellow出炉,70余位华人入选
  4. C++ 相关职位的要求
  5. 分享Appmakr式的简易App制作8大工具
  6. 读书笔记:《明朝那些事第三部:妖孽宫廷》
  7. 用计算机如何修改wif密码,电脑怎么修改无线网(WIFI)密码?
  8. spring cloud拓扑图
  9. 什么是cosmos?
  10. SQL server 2000个人版 下载地址