关于操作符

1.操作符分类:
算术操作符: + - * / %
移位操作符: << >>
位操作符: & | ^
赋值操作符: = += -= *= /= %= <<= >>= &= |= ^=
单⽬操作符: !、 ++ -- & * + - ~ sizeof ( 类型 )
关系操作符: > >= < <= == !=
逻辑操作符: && ||
条件操作符: ? :
逗号表达式: ,
下标引⽤: []
函数调⽤: ()
结构成员访问: . ->
2.进制转换:
我们平时经常能听到二进制,十进制,十六进制,八进制等话术,这究竟是什么意思呢?
其实这只是数值的表示形式而已。
比如:15的各种进制表示:
十进制:15
二进制:1111
八进制:17
十六进制:F
十进制里的数是1~9,那么同理二进制的数就是1~2.
这里的进制转换基础就不详细介绍了,相信大家都是有基础的国家栋才。
十进制转二进制:这里取的整数是125,将十进制整数不断除以2,所得余数从下向上数所得结果就是二进制
所以十进制的125转化为二进制就是1111101.
二进制转化八进制:二进制最大的数是7,用二进制表示就是111,所以二进制用三个二进制来表示八进制前面不够的补零,也可以省略。
二进制转化十六进制:同二进制转化八进制的道理,十六进制最大的数是F,也就是15,用二进制表示就是1111,所以我们用四个二进制数表示十六进制。
如:2进制的01101011,换成16进制:0x6b,16进制表⽰的时候前⾯加0 X
3.原码,反码,补码:
整数的2进制表⽰⽅法有三种,即原码、反码和补码
有符号数三种表示方法分为符号位和数值位,二进制中最高的一位就是符号位,剩下的就是数值位
正数的原码反码补码都一样。负数的原码反码补码各不相同,原码数值位全部取反就是反码,反码加1就是补码。补码求原码也是取反加1。
对于整形来说内存中存放的就是补码,这是有原因的:
在计算机系统中,数值⼀律⽤补码来表⽰和存储。原因在于,使⽤补码,可以将符号位和数值域统⼀ 处理;同时,加法和减法也可以统⼀处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路
4.移位操作符:
移位操作符只能用于整数
<< 左移操作符
>> 右移操作符
左移操作符,顾名思义,将二进制数向左移动
而右移操作符要比左移操作符复杂点,它分为两种,一种是逻辑右移,一种是算数右移。
逻辑右移同左移操作符一样,二进制向右移动,左边补零。
算数右移中二进制数向右移动,最左边符号位是什么就补什么。
警告⚠️:
对于移位运算符,不要移动负数位,这个是标准未定义的。例如:10>>-1
5.位操作符:&,|,^,~:
&:按位与
|:按位或
^:按位异或
~:按位取反
注: 他们的操作数必须是整数
&是左右都是1,才是1,否则位零
|是左右只要有一个1就是1,全是零才是零
^是两边不一样就是1,一样的话就是零
~a将二进制全部取反
6.单目操作符(只有一个操作数):
!、 ++ -- & * + - ~ sizeof ( 类型 )
7.逗号表达式:
m=(a,b,c)的结果是m=c,当然这里不是简简单单的直接等于c,而是要从前往后运算最后求出c的值,再将值赋给m,因为前面可能会改变c。
8.下标访问[]、函数调⽤()
[ ]是下标引用操作符。 操作数:⼀个数组名 + ⼀个索引值(下标)
( )是函数调用操作符。 接受⼀个或者多个操作数:第⼀个操作数是函数名,剩余的操作数就是传递给函数的参数。
9.结构成员访问操作符:
c语言已经给我们提供了许多内置类型,如int,char,flaot等,但只有这些内置类型还不够,就比如我们要形容一个学生时,肯定不是单一的描述整数或者浮点数,字符,而是包括多项,这时候我们就要用到结构体了
结构是⼀些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量,如:
标量、数组、指针,甚⾄是其他结构体.
结构的声明:
struct tag
{
 member-list;
}variable-list;

在描述一个学生时:
struct Stu
{
 char name[20];//名字
 int age;//年龄
 char sex[5];//性别
 char id[20];//学号
};

结构体定义与初始化:

//代码1:变量的定义
struct Point
{
 int x;
 int y;
}p1; //声明类型的同时定义变量p1
struct Point p2; //定义结构体变量p2
//代码2:初始化。
struct Point p3 = {10, 20};
struct Stu //类型声明
{
 char name[15];//名字
 int age; //年龄
};
struct Stu s1 = {"zhangsan", 20};//初始化
struct Stu s2 = {.age=20, .name="lisi"};//指定顺序初始化
//代码3

struct Node
{
 int data;
 struct Point p;
 struct Node* next; 
}n1 = {10, {4,5}, NULL}; //结构体嵌套初始化
struct Node n2 = {20, {5, 6}, NULL};//结构体嵌套初始化

这里需要注意结构体初始化可以按顺序直接初始化,如果不想按顺序需要规范格式(有个点.):.age

结构体成员的直接访问需要用到点操作符(.),使⽤⽅式:结构体变量.成员名

这里还能用指针间接访问结构体成员,放后面说,因为我还没学到。

10.操作符的优先级和结合性:

C语言操作符有两个很重要的属性,优先级和结合性,这两个属性决定了计算时的运算顺序。

优先级:优先级指的是,如果⼀个表达式包含多个运算符,哪个运算符应该优先执⾏如上面,乘法的优先级比加法高,所以先执行乘法再执行加法。这里的各种操作符优先级比较可以进入网址观察https://zh.cppreference.com/w/c/language/operator_precedence

结合性:当操作符两边优先级相同就要看结合性了,⼤部分运算符是左结合(从左到右执⾏),少数运算符是右结合(从右到左执⾏),⽐如赋值运算符( = )。更多的结合性也通过上方网址观察即可。

11.表达式求值:

整形提升:C语⾔中整型算术运算总是⾄少以缺省(默认)整型类型的精度来进⾏的。

整形提升的意义:表达式的整型运算要在CPU的相应运算器件内执⾏,CPU内整型运算器(ALU)的操作数的字节⻓度⼀般就是int的字节⻓度,同时也是CPU的通⽤寄存器的⻓度。 因此,即使两个char类型的相加,在CPU执⾏时实际上也要先转换为CPU内整型操作数的标准⻓度。 通⽤CPU(general-purpose CPU)是难以直接实现两个8⽐特字节直接相加运算(虽然机器指令中 可能有这种字节相加指令)。所以,表达式中各种⻓度可能⼩于int⻓度的整型值,都必须先转换为int或unsigned int,然后才能送⼊CPU去执⾏运算。

算数转换:如果某个操作符的各个操作数属于不同的类型,那么除⾮其中⼀个操作数的转换为另⼀个操作数的类型,否则操作就⽆法进⾏。

综上所述呢,当我们在写代码时,尽量不要把表达式写的太复杂,可以分开一条一条写,没必要追求一句代码就把解决,因为就算我们确定了优先级和结合性,表达式的运算路径也可能有多种,存在一定的风险。

  • 22
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值