C语言:操作符详解

操作符的知识内容比较多,十分广泛。但是每一个知识点的难度都不高,稍有了解很快就能掌握。话不多说让我们开始吧.

目录

1.算术操作符

2.移位操作符

2.1 左移操作符 <<

2.2 右移操作符 >>

3.位操作符

3.1   按位与  &

 3.2   按位或  |

 3.3   按位异或  ^

4.赋值操作符

5.单目操作符

 5.1  !

 5.2  ~

 5.3 前置++、后置++

6.关系操作符

7. 逻辑操作符

8.条件操作符 

9.逗号表达式 

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

10.1   []  下标引用操作符

10.2  ( ) 函数调用操作符

10.3 访问结构体成员

11.表达式求值:隐式类型转换

11.1 整形提升

11.2 算数转化

11.3 操作符的属性


1.算术操作符

算术操作符有:+  -  *  /  %

值得注意的是,%只能用于整数,/两边需要注意输出的类型

 如果想要除法输出的是小数,那么/左右两边至少有一边需要输入的是带有小数点的数字。

2.移位操作符

首先我们必须知道,整数有三种二进制的表示形式:原码、反码和补码。

正整数:原码、反码和补码相同

负整数:原码、反码和补码不同,并且要进行计算

 2.1 左移操作符 <<

 

 其实计算的时候可以简单看成往左移1就是乘了2的1次方

2.2 右移操作符 >>

右移操作符分为算术右移和逻辑右移。

逻辑移位:左边用0填充,右边丢弃

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

但常见的编译器是算数右移

 另外,需要补充的是移位运算符不要移动负数位,如<<-1不行。

3.位操作符

位操作符有:&  按位与        |  按位或      ^  按位异或  

3.1   按位与  &

二进制数都为1才为1

 3.2   按位或  |

二进制数有1为1,没有1为0

 3.3   按位异或  ^

二进制数相同为0,不同为1

4.赋值操作符

赋值 =;复合赋值符:+=    -=    *=    /=    %=    >>=    <<=    &=    |=    ^=

特别注意:赋值是一个等于号!!!

a = a+10;
a += 10;
意思是一样的

5.单目操作符

单目操作符,顾名思义是对一个数字进行操作

!            逻辑反操作

-            负值

+           正值

&           取地址

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

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

--           前置、后置--

++         前置、后置++

*            间接访问操作符(解引用操作符)

(类型)    强制类型转换

 5.1  !

!            逻辑反操作:把真(非零的数)变为假(0),假(0)变为真(1)

 5.2  ~

~           按位(位指的是补码的二进制)取反

首先搞懂  “反码”,“取反”,“按位取反(~)”,这3个概念是不一样的。

取反:0变1,1变0

反码:正数的反码是其本身,对于负数其符号位不变其它各位取反(0变1,1变0)

这里先以-3为例,-3的32bit取8位

原码为1000 0011

反码为1111 1100

补码为1111 1101(反码+1)

补码取反:0000 0010

新数字反码、补码、原码都一样,这个数字为2

1. 所有正整数的按位取反是其本身+1的负数

2. 所有负整数的按位取反是其本身+1的绝对值

3. 零的按位取反是 -1(0在数学界既不是正数也不是负数) 

5.3 前置++、后置++

++a,代表a在使用前自加1,再使用

a++,代表a在使用后自加1

6.关系操作符

>      >=      <      <=      !=      ==

需要额外注意的是,  =  和  ==  一定要区分清楚!!!

我们可以这样写

int a = 5;

if(5==a)
{

}

这样子在编译的时候就容易发现错误

7. 逻辑操作符

逻辑与 &&

逻辑或  ||

现在有一道题:

#include <stdio.h>
int main()
{
    int i = 0,a=0,b=2,c=3,d=4;
    i = a++ && ++b && d++;
    printf("a = %dn b = %dn c = %dnd = %dn", a, b, c, d);
    return 0; }
//程序输出的结果是什么?

a++时,因为a为0,所以所有的&&都不会再进行运算了。故打印出来只有a比初始化时加了1

 我们把题目改一下:

#include <stdio.h>
int main()
{
    int i = 1,a=0,b=2,c=3,d=4;
    i = a++ || ++b || d++;
    printf("a = %dn b = %dn c = %dnd = %dn", a, b, c, d);
    return 0; }
//程序输出的结果是什么?

 a++时,||左边为1,判定为真,所以右边的||都不算了

8.条件操作符 

exp1 ? exp2 : exp3

问号前面的是真执行exp2,是假执行exp3

9.逗号表达式 

exp1, exp2, exp3, …expN

用法如下:

int main()
{
int a = 3;
int b = 4;
int c = 5
int d = (a+=2,b=a-c,c=a+2*b);

printf("%d",d);
return 0;
}

执行的是最后一个逗号之后的值

 同时可以用逗号表达式简化一些表达:

//代码1
int a = 1;
int b = 2;
int c = (a>b, a=b+10, a, b=a+1);//逗号表达式
c是多少?
//代码2
if (a =b + 1, c=a / 2, d > 0)
//代码3 a = get_val();
count_val(a);
while (a > 0) {
 //业务处理
        a = get_val();
        count_val(a);
}
如果使用逗号表达式,改写:
while (a = get_val(), count_val(a), a>0) {
         //业务处理
}

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

10.1   []  下标引用操作符

int arr[10];
arr[9] = 10;//arr数组的第十个元素是10

[] 的两个操作数为 arr和9,arr和9可以互换位置,但不常见。

10.2  ( ) 函数调用操作符

接受一个或者多个操作数:第一个操作数是函数名,剩余的操作数就是传递给函数的参数。

#include <stdio.h>
 void test1()
 {
 printf("hehen");
 }
 void test2(const char *str)
 {
 printf("%sn", str);
 }
 int main()
 {
 test1();            //实用()作为函数调用操作符。
 test2("hello bit.");//实用()作为函数调用操作符。
 return 0;
 }

10.3 访问结构体成员

 .结构体

后面我们还会详细的讲解这部分内容

11.表达式求值:隐式类型转换

11.1 整形提升

首先我们先看一段代码 

 结果为什么是-125呢?这里涉及到整形提升这个概念。

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

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

简单来说,就是非int(unsigned int)的值应该先转化为int(unsigned int)进行储存,进行计算

具体怎么运算呢?

5在内存中有32个比特位,00000000000000000000000000000101

但是a是char类型的,只能存储8个比特位。所以5就被“截断”了。a中存储的只有0000 0101

同理,126在b中被截断为0111 1110

如何进行整形提升呢?

整形提升是按照变量的数据类型的符号位来提升的

(负数高位补1,整数或无符号数高位补0)

00000000000000000000000000000101  ---a

000000000000000000000000001111110  ---b

00000000000000000000000010000011  ---相加后

所以此时c就是 1000 0011 此时又因为c是char类型

再次整形提升:

11111111111111111111111110000011 ---补码

11111111111111111111111110000010 ---反码(补码-1)

10000000000000000000001111101 ---原码>> -125

这就是提升之后的结果。另外提一嘴:只有char和short类型的变量才会发生整形提升。

11.2 算数转化

大于4个字节的类型的转换不叫整形提升,而交做算数转化。

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

如果某个操作数的类型在上面这个列表中排名较低,那么首先要转换为另外一个操作数的类型后执行运算。如10/3不进行算数转换算出来的是int类型。

 补充:sizeof内部的表达式不进行计算

int main()
{
short s = 20;
int a = 5;
printf("%dn",sizeof(s = a + 4));
printf("%dn",s)
return 0;
}

 最终的结果是2和20。

11.3 操作符的属性

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

1. 操作符的优先级

2. 操作符的结合性

3. 是否控制求值顺序。

我们平时在写代码的时候一定要避免写出有歧义的代码。多种操作符夹杂在一起,有时会让不同编译器都出现不同的结果。

//代码3-非法表达式
int main()
{
 int i = 10;
 i = i-- - --i * ( i = -3 ) * i++ + ++i;
 printf("i = %dn", i);
 return 0;
}

 这个代码在不同的编译器里面出现了很多种不同的结果。这是非常糟糕的写法,一定要避免写出这样子的代码。

那么今天的内容就到这里了。操作符内容十分庞大,但其实都不难。自己多去理解理解就好啦~

 这一期的内容真的鸽了很久很久,如果觉得还不错的话把你们的赞留下吧!感谢!

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>