初阶C语言 第四章-------《操作符》 (逻辑操作符,算术操作符,逗号表达式,三目操作符)知识点+基本练习题+深入细节+通俗易懂+完整思维导图+建议收藏

简介: 初阶C语言 第四章-------《操作符》 (逻辑操作符,算术操作符,逗号表达式,三目操作符)知识点+基本练习题+深入细节+通俗易懂+完整思维导图+建议收藏

绪论

       书接上文,不知道数组的两个小游戏是否让你头昏眼花了,但请你保持良好的自信心,百炼自成钢,在小游戏里面犯的错,最终都将转化成你的经验!!本章将写道 操作符 该章理论偏多,但是关于二进制的一些问题会稍微有点麻烦。image.png

所以安全带系好,发车啦(建议电脑观看)。


思维导图:

image.png

要XMind思维导图的话可以私信哈

目录


1.算数操作符

2.位移操作符

3.位操作符

4.赋值操作符

5.单目操作符

6.关系操作符

7.逻辑操作符

8.条件操作符

9.逗号表达式

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

11.表达式求值

11.1隐式类型转换

11.2算术转换

11.3操作符属性

1.算数操作符

知识点:

算数操作符:+ ,- ,*  ,  /  , %

其加减乘除大概就是和数学中的一样的进行计算

而最后的 % :他叫取模,其实也并不陌生就是除法的余数:3 % 2 == 1

细节(注意点):

除%操作符之外的其他加减乘除都可用作到浮点数的计算,也就是 %操作符的两端只能是整数,返回的也是整除之后余的。

对于 /  来说当他的两个操作数(除法的两端)都为整数时执行整数除法,而只要其中有浮点数就将回执行浮点数除法 : 3 / 2.0  =  1.500000

2.位移操作符

知识点:

位移操作符:>> , <<  

他们两个是用来移动二进制位的,且位移操作符的操作符只能是整数

练习:

细节:

先了解一下二进制位:

在计算机中所有的运算都是通过转化成二进制后才能再进行计算,所以无法转化成二进制的东西计算机无法运算

一个int类型的数他是占四个字节的而1个字节有是8bit所以四个字节就是32个bit

所以2可以表示成:

00000000000000000000000000000010

== (0 * 2 ^ 0  ) +(  1 * 2 ^ 1 )+ (0 * 10 ^ 3 )+ .... == 2 ( ^ 表示次方)

如十进制中的12 ==(  2 * 10 ^ 0 ) +  ( 1 * 10 ^ 1)


其次我们要了解,原码,反码,补码

原码:就是一个数直接写出来的二进制形式

2:00000000000000000000000000000010

-2:10000000000000000000000000000010  

(-2的二进制会在最前面加上1代表负数的   符号位 )

反码:原码按位取反的结果,也就是除符号0变成1,1变成0。

补码:反码+1的结果

所以他们的转换方式:原码按位取反得到反码再+1得到补码

所以补码返回成原码的方法就是 先-1,在按位取法;

但神奇的是补码进行原码的转化方法也能返回成原码也就是:补码先按位取法再加1,也会变回原码

注意:在内存中的二进制都是以补码的形式存储的,而我们看到的是原码,

          正数的原,反,补相同,故负数则不同

下面以一个二进制-2来展示刚刚的原反补关系

原码:10000000000000000000000000000010

反码:111111111111111111111111111111111101

补码:111111111111111111111111111111111110

1.倒回去-1,取反

反码:111111111111111111111111111111111101

原码:10000000000000000000000000000010

2.以原码转化的方法

补码:111111111111111111111111111111111110

反码按位取反:

        10000000000000000000000000000001

在加1:

        10000000000000000000000000000010

附:二进制的加减也和十进制一样,不够减就向前面借(借的是2),加多了就向前增(到2就进)

如:1+1:

00000000000000000000000000000001

00000000000000000000000000000001

00000000000000000000000000000010

2-1:

00000000000000000000000000000010

00000000000000000000000000000001

00000000000000000000000000000001

左移操作符(<<):左抛弃,右边补0

右移操作符(>>):算术右移(右边抛弃,左边补符号位),逻辑右移(右边抛弃,左边补0),对于大部分编译器都是算术右移,所以下面例子以算术来看

通过对二进制的一定了解,现在再看左右位移操作符,也就是将2进制位整体挪一下位置

以-2来向左和右各移一位来看:也就是 -2 << 1 , -2  >> 1

image.png

没有移负数这种操作哈(3 >> -2    ?)

3.位操作符

知识点:

位操作符:& , | ,^

进行改变二进制的一种操作符

&:按位与:将两个二进制按位与比较每一位数有0就与成0,都为1才与成1;一假则假

| :按位或:将两个二进制按位或比较每一位数有1就或成1,都为0才或成0;一真则真

^:按位异或:每位二进制里比较各个位的相同就为0,不同就为

细节:

操作数必须为整数,他是在内存中计算的所以他们在计算过程中是补码,最终还要转化成原码出来

练习:

下面通过练习再来更加深刻的了解上面的位操作符

#include<stdio.h>
int main()
{
    int num1 = 1;
    int num2 = 2;
    num1 & num2;
//00000000000000000000000000000001
//00000000000000000000000000000010
//1 & 2 = 0;按位与一假则假
//00000000000000000000000000000000
    num1| num2;
//00000000000000000000000000000001
//00000000000000000000000000000010
//1 | 2 = 3;按位或一真则真
//00000000000000000000000000000011
    num1 ^ num2;
//00000000000000000000000000000001
//00000000000000000000000000000010
//1 & 2 = 3;按位异或,两同为0,相异为1
//00000000000000000000000000000011
    return 0;
}

不创建临时变量的前提转交换两个数

求一个二进制中有几个1234

4.赋值操作符

知识点:

赋值操作符:=

附:+= , -= ,  *= , /= , %= , >>=  , <<= , &= , ^= , |=  

例如 +=  : a = a + 2   :  a += 2  ,这两个效果一样,其他同理

>>= :  a = a >> 3 ; a >>= 3

5.单目操作符

知识点:

单目操作符:! , - , + , & , sizeof , ~ , -- , ++ , * , ()

! :逻辑反操作符(将真变成假(0))

- :(负值)和中数学一样

+:(正值)没什么用并不能将负数变成正数

&:(取地址)只要是变量都会有一个地址,一般用在指针处

sizeof :求操作数的类型大小(如int类型就是4byte)

~ :对二进制进行按位取反

++ , -- :前,后置减减,前置是表示在使用前减减,后置则是表示在使用后在减减

++ -- 在使用过程中会改变值,即a-- : a在使用后 a = a -1

* : 解应用操作符,一般用在指针处

():强制类型转换,如 3.14原本是一个浮点型的,

!:

while(1)//此括号处因为为非0使用为真可以进入循环
{
。。。;
}
while(!1)//虽然他是非0但加上!就变成了(0)假
{
.......;
}
while(!0)//此处本为假但是通过反操作符使他变成(1)真
{
...;
}

细节:

附:

unsigned:

无符号的,如-1看成无符号时,就会将他在内存中的补码直接看成原码

-1 原码:10000000000000000000000000000001

    反码:111111111111111111111111111111111110

    补码:   111111111111111111111111111111111111

所以从上面来看如果unsigned int = -1 将会变一个很大的值

sizeof:

int a = 2 ; sizeof(a) == sizeof(int) == sizeof a != sizeof int(数据类型必须加括号)

所以sizeof并不是函数,而是操作符

当sizeof在函数内部使用时要注意参数类型是否是指针,如果是指针其大小将会是4/8

并且注意数组作为形参时其本质也是指针,如下

#include <stdio.h>
void test1(int arr[])
{
 printf("%d\n", sizeof(arr));
}
void test2(char ch[])
{
 printf("%d\n", sizeof(ch));
}
int main()
{
 int arr[10] = {0};
 char ch[10] = {0};
 printf("%d\n", sizeof(arr));
 printf("%d\n", sizeof(ch));
 test1(arr);
 test2(ch);
 return 0;
}

上面这串代码最终将会打印

40

10

4

4

40因为int为4个字节,而数组大小有10个最终计算的大小就是4*10=40

同理10是因为char类型是1个字节,有10个元素10*1 = 10

而后面两个均为4是因为在形参处的数组其本质是指针他也可以写成(char*ch,int * arr)并且指针的大小都是4个字节,与其的类型无关(其类型关系我会在指针章在细说),所以sizeof就会算出4来

6.关系操作符

知识点:

关系操作符: < , > , >= , <= , == , !=

关系操作符和数学中的一样,

其中== 是比较性的 等号,注意与 赋值操作符 = 区别

!=  比较是否 不等

7.逻辑操作符

知识点:

逻辑操作符:&& , ||

&& : 就是与   , || 就是或

&&:判断其两个操作数是否为真(非0就为真),同时为真才为真(即一假则假)

||  :判断其两个操作数是否有一个为真,一个为真就为真(即一真则真)

其实就和数学中的或(∨)与(∧)一样

细节:

当连续使用时,从左往右一次进行

短路:

&&操作符,他是先判断左边,若左边已经为假,他再看右边的了

||操作符同理,他是也是先判断左边,但当左边为真是他就不会再看右边是否为真了

练习:

360笔试题

8.条件操作符(三目操作符)

知识点:

条件操作符:exp1 ? exp2 : exp3

当条件1(exp1)满足条件时就会进行条件2(exp2)中 , 若exp1不满足则进入exp3中

细节:

image.png

他就好比是if语句

if(exp1)
{
    exp2;
}
else
{
    exp3;
}

9.逗号表达式

知识点:

逗号表达式: exp1 ,exp2 , exp3 ,.....

从左往右进入表达式,其中可能各个表达式会相互影响,也可能不影响,但最终结果由最后一个来定。

下面通过代码来更好的了解其

int main()
{
    int a = 10;
    int b = 20;
    int c = (a ,b -= 10, a += 10 , b += a);
    //逗号表达式从左往右以此计算表达式,最终取最后的表达式
    // c == 30;
}

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

知识点:

下标引用,函数调用和结构体成员:[ ] ,  ( ) ,  .  ,   ->

[ ]下标引用操作符:就是对数组的内容进行引用如arr[2]

( )函数调用操作符:就是在函数时所用的括号,其有两个操作数一个是函数名,另一个是就是传递给函数的参数

. 和 -> 都是用来访问结构体成员的其用法是 结构体名.结构体成员名  ; 结构体指针 -> 成员名

#include <stdio.h>

#include <stdio.h>
struct Stu
{
    char name[10];
    int age;
    char sex[5];
    double score;
};
void set_age2(struct Stu* pStu)
{
    (*pStu).age = 18;//其简易方法如下 
    pStu->age = 18;//结构成员访问
}
int main()
{
    struct Stu stu;
    struct Stu* pStu = &stu;//结构成员访问
    pStu->age = 20;//结构成员访问
    stu.age = 20;//结构成员访问
    set_age2(&stu);
    return 0;
}

11.表达式求值

表达式求值有一定的顺序,一部分由操作符的优先级和结合性决定

而有些操作数在求值过程中可能要转化成其他类型

11.1隐式类型转换

我们所需要知道的知识点:

在整数运算中总是至少以整形类型的精度进行的,所以为了这个精度一些小于整形大小的如短整形(short)字符(char)都会先被转换成整形再进行计算,这种转换被称作整形提升

整形提升的意义:

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

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

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

细节:

如何进行整形提升:

如char a = 1;其的二进制位因为是char类型(1个字节)所以只有8bit即 00000001

整形提升时,高位补其的符号位,即00000000000000000000000000000001

若char b = 2;同理其最后的整形提升成00000000000000000000000000000011

char c = a + b ;他们在计算过程中回先整形提升后再进行计算出后再进行截断8bit的字符型

即:00000000000000000000000000000100 -> 00000100

隐式的整形提升

int main()
{
 char a = 0xb6;
 short b = 0xb600;
 int c = 0xb6000000;
 if(a==0xb6)//此处本应该相等进入,但是因为有操作符== ,就导致其会进行整形提升
 printf("a");
 if(b==0xb600)//同上
 printf("b");
 if(c==0xb6000000)
 printf("c");
 return 0;
}
int main()
{
 char c = 1;
 printf("%u\n", sizeof(c));//而此处没有操作符就不会提升
 printf("%u\n", sizeof(+c));//同上因为有操作符(+)就导致其会整形提升最终求出的就是4字节
 printf("%u\n", sizeof(-c));
 return 0;
}

当有操作符时就会进行整形提升

11.2算术转换

知识点:

当不同类型的操作数进行计算时,必须转换成相同类型的才能继续继续计算。

他的转换方法时将低的转换到高的

long double   高

double

float

unsigned long int

long int

unsigned int

int                 低

int a = 3;

float b = 3.5f;

a + f 时就要把int类型的转换成float

11.3操作符属性

知识点:

对复杂的表达式,影响其求值的有三个因素,1.操作符的优先级,2.操作符的结合性,3.是否控制求值所需

image.png

细节:

尽管我们了解了各种的操作符的优先级,结合性。但仍然不可能将所有代码问题都解决

如:int i = 1;

int a = (i++) + (i++) + (i++) 像这种我们仍然无法不断到底那个i先++

本章完。预知后事如何,暂听下回分说。

相关文章
|
2天前
|
存储 编译器 C语言
C语言---操作符详解(1)
C语言---操作符详解
|
9天前
|
存储 C语言 索引
【C语言基础】:操作符详解(二)
【C语言基础】:操作符详解(二)
|
2天前
|
编译器 C语言 C++
C语言---操作符详解(2)
C语言---操作符详解
|
9天前
|
存储 编译器 C语言
【C语言基础】:操作符详解(一)
【C语言基础】:操作符详解(一)
TU^
|
9天前
|
存储 C语言
C语言之操作符
C语言之操作符
TU^
10 0
|
2天前
|
C语言
C语言---函数---请输入乘法口诀表的行,来打印几几乘法表
C语言---函数---请输入乘法口诀表的行,来打印几几乘法表
|
2天前
|
C语言
C语言--函数递归与迭代
C语言--函数递归与迭代
|
2天前
|
C语言 C++
C语言----C语言内存函数
C语言----C语言内存函数
|
2天前
|
C语言
C语言----字符函数和字符串函数(4)
C语言----字符函数和字符串函数
|
2天前
|
算法 C语言
C语言----字符函数和字符串函数(3)
C语言----字符函数和字符串函数
11 0