当前位置: 首页 > ds >正文

C语言——操作符

一.操作符的分类

  • 算术操作符: +   -   *   /   %
  • 移位操作符:<<  >>
  • 位操作符: &  |  ^
  • 赋值操作符: =    +=   -=    *=    /=    %=    >=    &=    |=    ^=
  • 单⽬操作符: !  ++   --   &   *   +   -    ~   sizeof  ( 类型 )
  • 关系操作符: >   >=   <   <=   ==  !=
  • 逻辑操作符:&&  || !  ++   --   &   *   +   -    ~   sizeof  ( 类型 )
  • 条件操作符:? :
  • 逗号表达式:,
  • 下标引用:[ ]
  • 函数调用:()
  • 结构成员访问:.    - >  

二.二进制和进制转换

计算机能够识别的是2进制信息,数据在内存中存出的时候,也是以2进制的形式存储的

2进制转10进制:

10进制转换为2进制

2进制转化为8进制

  8进制的数字每⼀位是0~7的,0~7的数字,各⾃写成2进制,最多有3个2进制位就⾜够了,⽐如7的二进制是111,所以在2进制转8进制数的时候,从2进制序列中右边低位开始向左每3个2进制位会换算一个8进制位,剩余不够3个2进制位的直接换算。 如:2进制的01101011,换成8进制:0153,0开头的数字,会被当做8进制。

例:

2进制转换为16进制

16进制的数字每⼀位是0~9,a~f的,0~9,a~f的数字,各⾃写成2进制,最多有4个2进制位就足够了, 比如f的二进制是1111,所以在2进制转16进制数的时候,从2进制序列中右边低位开始向左每4个2进 制位会换算⼀个16进制位,剩余不够4个二进制位的直接换算。 如:2进制的01101011,换成16进制:0x6b,16进制表示的时候前⾯加0x

例:

三.原码,反码,补码

原码::直接将数值按照正负数的形式翻译成⼆进制得到的就是原码

反码:将原码的符号位不变,其他位依次按位取反就可以得到反码。

补码:反码+1就得到补码。补码得到原码也是可以使⽤:取反,+1的操作。

正整数的原,反,补码都相同。

负整数的三种表示方法各不相同

整数(有符号整数,无符号整数)的2进制表示方法有三种,即原码、反码和补码

有符号整数的三种表示方法均有符号位数值位两部分,2进制序列中,最高位的1位是被当做符号 位,剩余的都是数值位。

符号位都是0表示正,1表示负。

无符号整数的三种 2 进制表⽰相同,没有符号位,每⼀位都是数值位。

对于整形来说:数据存放内存中其实存放的是补码。

四.移位操作符

移位操作符只能对整数进行移位,移动的是二进制位(存储在内存中的补码)

<<左移操作符

移位规则:左边抛弃,右边补零

int main()
{int a=6;int b=(a<<1)printf("%d\n",b);return 0;
}

最后a不没有变,结果是b变了,以为之后为12

>>右移操作符

移位规则:首先右移运算分两种(具体哪种取决于编译器):

1.逻辑右移:左边⽤0填充,右边丢弃

2.算术右移:左边⽤原该值的符号位填充,右边丢弃

对于移位运算符,不要移动负数位!

五.位操作符:& | ^ ~

&:按位与

|:按位或

^:按位异或(对应的二进制位,相同为0,相异为1)

        零和任何数异或还是任何数,异或支持交换律

~:按位取反(对应的二进制位,原来是0变成1,原来是1变成0)

以上操作符的操作数必须是整数

这里举两个例子应用一下

  • 编写代码将13二进制序列的第5位修改为1,然后再改回0
int main()
{int a = 13;a |= (1 << (5 - 1));printf("%d\n", a);//29
/*
13=000011011=00010000
按位或00011101
*/a &= ~(1 << (5 - 1));
/*
29=0001110111101111
按位与00001101
*/return 0;
}

  • 不创建临时变量(第三个变量),实现两个整数的交换
int main()
{
//0与任何数按位异或都为任何数int a=10;int b=20;a=a^b;//a'=a^bb=a^b;//b=a'^b=a^b^b=aa=a^b;//a=a^b^a=bprintf("a=%d b=%d\n",a,b);return 0;
}

六.单目操作符

!  ++   --   &   *   +   -    ~   sizeof  ( 类型 )

七.逗号表达式

exp1,exp2,exp3,...expN

逗号表达式,从左向右依次执行,整个表达式的结果是最后一个表达式的结果

八.下标访问[ ],函数调用()

1.[ ]下标引用操作符

操作数:一个数组名+一个索引值(下标)

int arr[10];
arr[9]=10;//使用下标引用操作符
[ ]的两个操作是arr和9

2.函数调用操作符()

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

九.结构成员访问操作符

在学习这个操作符之前,我们得先知道一个概念:结构体

结构是⼀些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量,如: 标量、数组、指针,甚至是其他结构体

1.结构体的声明和结构体变量的创建和初始化

struct tag//(自定义的一个名字)
{member -list;//里面可以有一个或多个成员
}variable-list;//(可有可无)//例:描述一个学生
struct Stu
{char name[20];int age;char id[11];float score;
}s6,s7,s8;//声明的同时顺便创建了几个变量,可有可无,这是全局变量
struct Stu s4;//全局变量
int main()
{    int num=0;struct Stu s1;//结构体变量的创建,s1,s2,s3都是局部变量struct Stu s2={"zhangsan",20,"20240809",85.5f};//初始化用大括号struct Stu s3={.age=18,.name="wangcai",.score=95.5f,.id="20240801"};//想指定初始化那个这里就用到了结构访问操作符.去初始化return 0;}

2.结构体的嵌套

struct Peo
{char name[30];int age;char tele[12];
};
struct Ebook//实现一个通讯录,这个结构体就包含了另一个结构体
{struct Peo data[100];int count;
};
int main()
{struct Peo p1={"zhangsan",20,"12372324"};struct Ebook eb={{{"wangwu",19,"19378634"},{"cuihua",18,"28646375"}},0};printf("%s\n",p1.name);//访问结构体变量打印姓名(.结构成员访问操作符)printf("%s\n",p1.age);    printf("%s\n",eb.data[1].name);//打印翠花的名字return 0;
}

3,结构体成员的直接访问操作符.

使用方式:结构体变量.成员名

具体使用示例见上面代码

4.结构体成员的间接访问操作符->

使用方式:结构体指针->成员名

具体使用实例待后面学完指针详细说明,结构体也会在后面详细学习

十,操作符的优先级和结合性

1.优先级:

如果一个表达式包含很多操作符,我们需要知道那个操作符优先,优先级高的先进行计算

2.结合性:

如果两个运算符优先级相同,这时没法确定先算哪个就看结合性。根据运算是左结合还是右结合,决定执行顺序。

具体可参考下表

十一,表达式求值

1.整型提升

int main()
{int a=100;long c=100l;//编译器会默认100是整型,除非你在后面加个l,它会转变为long型long long b=100ll;//同理float f=3.14f;//这里规定会被默认为double类型,所以我们再后面加个f就会转换为float类型return 0;
}

C语言中整型算术运算总是至少以缺省(默认)整型类型的精度来进行的。 为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升

如何整型提升?

(1). 有符号整数提升是按照变量的数据类型的符号位来提升的

(2).无符号整数提升,高位补0

int main()
{
//char是有符号的,signed charchar a=20;//截断后存进了a,因为a一个字符只占了八个字节,存不下那么多所以要截断//000000000000000000010100//只有00010100存进了achar b=120;//发生截断//000000000000000001111000//01111000存进了bchar c=a+b;
//整型提升//a-00010100-提升000000000000000000010100//b-01111000-提升000000000000000001111000// 相加所得的是补码0000000000000000010001100//存进c里的为100001100printf("%d",c);//c提升后为111111111111111110001100-补码//打印的是原码-100000000000000001110100-转化为十进制就是-116return 0;
}

以上代码中b和a的值被提升为普通整型,然后再执行加法运算。 加法运算完成之后,结果将被截断,然后再存储于c中

打印结果就为-116

2.算术转换

如果某个操作符的各个操作数属于不同的类型,则除非其中⼀个操作数的转换为另⼀个操作数的类 型,否则操作就不能进行。这个我们不需要过多操心,编译器会自动转化

3.问题运算代码举例

(1)

c + --c

这个代码运算的问题是,前一个c的开始取值不知道,因为后一个--c先进行计算,不确定前一个c是初定义的值还是减减后的值

(2)

a*b + c*d + e*f

不确定是以下哪种顺序,因为以下都符合正确的优先级和结合性

(3)

int main()
{int answer;answer=fun()-fun()*fun();printf("%d\n",answer);return 0;
}

这个我们只能通过优先级知道先算乘法,再算减法,而上面三个fun函数调用先后顺序无法通过操作符的优先级确定,不一样的先后顺序就导致了结果的不同

所以我们尽量不要写那样运算符冗杂混乱的代码,不确定优先级的操作符可以加以括号进行辅助。

http://www.xdnf.cn/news/4687.html

相关文章:

  • VSCode怎么同时打开多个页面
  • 分区器(1)
  • 测度论——测度论思想的引出
  • Linux电源管理(7)_Wakeup events framework
  • 动态规划--线性dp
  • leeCode算法之独一无二出现次数
  • 【HarmonyOS 5】鸿蒙Web组件和内嵌网页双向通信DEMO示例
  • 晶体布局布线
  • 【CUDA C实战演练】CUDA介绍、安装、C代码示例
  • 电商双十一美妆数据分析(代码)
  • MapReduce中的分区器
  • Ceph 原理与集群配置
  • 网络技术基础,NAT,桥接,交换机,路由器
  • 关于Stream
  • paddle ocr 或 rapid ocr umi ocr 只识别了图片的下部分内容 解决方案
  • 如何避免“救火式管理”消耗精力
  • EEG设备的「减法哲学」:Mentalab Explore如何用8通道重构高质量脑电信号?
  • C++20新特新——02特性的补充
  • 数字乡村综合管理与服务平台软件需求规格说明文档
  • Office365功能特点
  • vue3:十二、图形看板- 基础准备+首行列表项展示
  • MySQL基础关键_011_视图
  • MCU怎么运行深度学习模型
  • 跨境电商生死局:动态IP如何重塑数据生态与运营效率
  • 【PhysUnits】2.2 Scalar<T> 标量元组结构体(scalar/mod.rs)
  • 文章记单词 | 第66篇(六级)
  • 数据库 postgresql 修改密码 sh
  • 大模型赋能:2D 写实数字人开启实时交互新时代
  • 利用并行处理提高LabVIEW程序执行速度
  • 详解0-1背包的状态转移表