C语言操作符详解

目录

1.算数操作符

  +  -  *  /  %

2.移位操作符

左移操作符   <<

右移操作符   >>

3.位操作符

3.1 按位与操作符 &  (按二进制位与)

3.2 按位(二进制位)或操作符  |

 3.3 按(二进制位)位异或  ^

4.赋值操作符

赋值  =   (判断符 ==)

复合赋值操作符

+=

-=

*=

/=

%=

>>=

<<=

&=

|=

^=

5.单目操作符(只有一个操作数)

5.1   !逻辑反操作     a=1为真         !a即为假(!a=0) 

5.2   -  负值

5.3   +  正值

5.4   & 取地址

5.5   sizeof  操作数的类型长度(以字节为单位)

        ​

5.6    ~   对一个数的二进制按位取反

5.7   --   前置、后置--

5.8   ++   前置、后置++

5.9   *   间接引用操作符(解引用操作符)

5.10   (类型)   强制类型转换

 6.关系操作符  >  >=  <  <=   !=  ==

7.逻辑操作符

  7.1   &&   逻辑与

  7.2   ||      逻辑或

8.条件操作符

 9.逗号表达式

 10.下标引用、函数调用和结构成员

        10.1 下标引用

        10.2  函数调用

 ​

         10.3 结构成员

11.表达式求值

11.1  隐式类型转换

11.2 算术转换

 12.3 操作符的属性

C语言操作符优先级


1.算数操作符

  +  -  *  /  %

加 减 乘 除 取余

ps:  %取余操作符的两个操作数必须为整数。

2.移位操作符

对操作数(整数)的二进制位进行操作,内存中存的是补码,也就是对补码进行操作

对于负整数而言:   原码:直接根据数值写出来的二进制序列就是原码

                            反码:原码符号位不变,其他位按位取反就是反码

                            补码:反码加 1 即补码

对于正整数而言:原码、反码、补码相同

左移操作符   <<

左边丢弃,右边补零


右移操作符   >>

1.逻辑移位

左边补零,右边丢弃

2.算术移位

左边用原该值的符号位填充,右边丢弃。

3.位操作符

3.1 按位与操作符 &  (按二进制位与)

int main()
{
	int a = 3;
	int b = 5;
	int c = a & b;
	printf("%d", c);
	return 0;
}

 运算逻辑: a   00000000000000000000000000000011

                 b   00000000000000000000000000000101

                 c    00000000000000000000000000000001

               a b  相对应的位置有一个为 0(假),则c 的相对应的位为 0(假)   有1假为假

               a b  相对应的位置都为 1 (真)时,  则c 的相对应的位为 1 (真)  有2真才为真

3.2 按位(二进制位)或操作符  |

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
//按位或
int main()
{
	int a = 3;
	int b = 5;
	int c = a | b;
	printf("%d", c);
	return 0;
}

 运算逻辑

 有真(1)即为真(1),两假(0)才为假(0)    1真为真,2假才为假

 3.3 按(二进制位)位异或  ^

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
//按位异或
int main()
{
	int a = 3;
	int b = 5;
	int c = a ^ b;
	printf("%d", c);
	return 0;
}

 

 运算逻辑

 相对应 bit 位相异即为真(1),相同即为假(0)         相异为真,相同则假

ps:a^a=0;   a^0=a

4.赋值操作符

赋值  =   (判断符 ==)

复合赋值操作符

+=

-=

*=

/=

%=

>>=

<<=

&=

|=

^=

例:a+=10       

       a=a+10;

5.单目操作符(只有一个操作数)

5.1   !逻辑反操作     a=1为真         !a即为假(!a=0) 

5.2   -  负值

5.3   +  正值

5.4   & 取地址

        与5.9 解引用操作符一起讲

5.5   sizeof  操作数的类型长度(以字节为单位)

        例:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

int main()
{
	int a = 10;//占用4个字节空间
	int arr[10] = {0};//占用4*10 个字节空间		初始化数组需 要 大括号 {0}
	printf("%d\n",sizeof(arr));//sizeof里面可放数组名
	printf("%d\n",sizeof(int [10]));//也可以放函数类型
	printf("%d\n", sizeof a);//计算 a 所占空间大小可以不用带括号,带也无妨,证明sizeof是一个操作            
                             //符并不是一个函数
	printf("%d\n", sizeof(int));//
	short s = 5;//占用2个字节空间
	printf("%d\n", sizeof(s = a + 2));//sizeof计算的仍是 s 这个短整型所占的空间大小
	printf("%d\n", s);//sizeof函数里面的表达式是不参与运算的,所以并不会影响 s 的值
	return 0;
}

        

        

5.6    ~   对一个数的二进制按位取反

        

5.7   --   前置、后置--

       --使用方法和++一致

5.8   ++   前置、后置++

5.9   *   间接引用操作符(解引用操作符)

        

 

5.10   (类型)   强制类型转换

 6.关系操作符  >  >=  <  <=   !=  ==

        可以用来判断变量之间的关系

         ps: 1. 比较两个字符串是否相等,不能使用  ==

                  2.  = 赋值          == 判断是否相等

7.逻辑操作符

  7.1   &&   逻辑与

        有一个为假都为假

 

         两个为真才为真

 有一个条件为假后面的都不用算了

  7.2   ||      逻辑或

     有一个条件为真后面的就不用算了

        与逻辑与相对

        应该为真即为真,两个为假才为假

8.条件操作符

      (三木操作符)

        exp1 ? exp2 :exp3 

例:

 9.逗号表达式

 10.下标引用、函数调用和结构成员

        10.1 下标引用

        10.2  函数调用

 

         10.3 结构成员

通过解引用操作符访问指针打印

 或者

 使用    ->     结构体 -> 成员名       

11.表达式求值

表达式求值的顺序一般是由操作符的优先性和结合性决定的。

同样,有些表达式的操作数在求值过程中可能需要转换为其他类型。

11.1  隐式类型转换

C语言中的整型算术运算总是至少以缺省整型类型的精度来进行的

为了获得这个精度,表达式中的字符和短整型操作数在使用之前转换为普通整型,这种转换称为 整型提升

ps:当操作数长度大于或等于普通整型长度时,便无须进行整型提升。

【整型提升的意义】:

表达式的整型运算要在cpu的相应运算器件内执行,cpu内整型运算器(ALU)的操作数的字节长度一般是 int 的字节长度,同时也是cpu的通用寄存器的长度。

因此即使两个 char 类型的相加,在cpu执行时实际上也要转换为cpu内整型操作数的标准长度。

通用cpu(general-purpose CPU)是难以直接实现两个8比特字节的直接相加运算(虽然机器指令中可能有这种字节相加的指令)。所以,表达式中各种可能小于 int 长度的整型值,都必须先转换为 int 换 unsigned int ,然后才能送入 cpu 去执行运算。

例:

 又例:

        再例

11.2 算术转换

如果某个操作符的各个操作数属于不同类型,那么除非其中一个操作数转换为另一个操作数的类型,否则操作无法进行。下面的层次体系称为寻常算术转换。

long double
double
float
unsigned long int
long int
unsigned int
int

如果某个操作数的类型在上面这个列表中排名较低,那么首先要转换为另外一个操作数的类型后执行运算。(向精度更高的去转换)(int >> long int)

警告: 但是算术转换要合理,要不然会有一些潜在的问题。

 12.3 操作符的属性                                                    

复杂表达式的求值有三个影响的因素。                                 

1. 操作符的优先级                                                                            

例:* / 优先于 + -                                                                                                    

2. 操作符的结合性                                                                                                    

3. 是否控制求值顺序。

两个相邻的操作符先执行哪个?取决于他们的优先级。

如果两者的优先级相同,取决于他们的结合性。

C语言操作符优先级                                                  

                 C语言操作符优先级

优先级

运算符

含    义

要求运算

对象的个数

结合方向

1

()

[]

->

.

圆括号

下标运算符

指向结构体成员运算符

结构体成员运算符

自左至右

2

!

逻辑非运算符

1

(单目运算符)

自右至左

~

按位取反运算符

++

自增运算符

--

自减运算符

-

负号运算符

(类型)

类型转换运算符

*

指针运算符

&

地址与运算符

sizeof

长度运算符

3

*

/

%

乘法运算符

除法运算符

求余运算符

2

(双目运算符)

自左至右

4

+

-

加法运算符

减法运算符

2

(双目运算符)

自左至右

5

<< 

>> 

左移运算符

右移运算符

2

(双目运算符)

6

<=

>=

关系运算符

2

(双目运算符)

自左至右

7

==

!=

等于运算符

不等于运算符

2

(双目运算符)

自左至右

8

&

按位与运算符

2

(双目运算符)

自左至右

9

^

按位异或运算符

2

(双目运算符)

自左至右

10

|

按位或运算符

2

(双目运算符)

自左至右

11

&&

逻辑与运算符

2

(双目运算符)

自左至右

12

||

逻辑或运算符

2

(双目运算符)

自左至右

13

? :

条件运算符

3

(三目运算)

自右至左

14

=

+=

-=

*=

/=

%=

>>=

<<=

&=

^=

|=

赋值运算符

2

自右至左

15

,

逗号运算符

自左至右

一些问题表达式

 注释:代码1在计算的时候,由于*比+的优先级高,只能保证,*的计算是比+早,但是优先级并 不能决定第三个*比第一个+早执行。 

注释:同上,操作符的优先级只能决定自减--的运算在+的运算的前面,但是我们并没有办法得 知,+操作符的左操作数的获取在右操作数之前还是之后求值,所以结果是不可预测的,是有歧义 的。

 《c和指针》作者测试 多个编译器测试结果

值 编译器                                                                                                    

—128          Tandy 6000 Xenix 3.2

—95            Think C 5.02(Macintosh)                                                  

—86            IBM PowerPC AIX 3.2.5                                                  

—85            Sun Sparc cc(K&C编译器)                                                  

—63            gcc,HP_UX 9.0,Power C 2.0.0

4                  Sun Sparc acc(K&C编译器)                                                  

21                Turbo C/C++ 4.5

22                 FreeBSD 2.1 R

30                 Dec Alpha OSF1 2.0

36                 Dec VAX/VMS

42                 Microsoft C 5.1

纳尼? 

 

 

这个代码有没有实际的问题?                                                                  

有问题!

虽然在大多数的编译器上求得结果都是相同的。 但是上述代码 answer = fun() - fun() * fun(); 中我们只能通过操作符的优先级得知:先算乘法, 再算减法。 函数的调用先后顺序无法通过操作符的优先级确定。

总结:我们写出的表达式如果不能通过操作符的属性确定唯一的计算路径,那这个表达式就是存在问题的。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值