c语言操作符

目录

运算符 

 移位操作符

左移操作符

右移操作符

位操作符

 按位与&

 按位或|

按位异或^

异或交换数字

计算二进制中1的个数

关系操作符

逻辑操作符

条件操作符

 逗号表达式

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

 隐式类型转换

整形提升实例:

算术转换

操作符属性

问题表达式


运算符 

加减乘除没什么好说的,注意除法计算除号两边至少有一个数为小数时才进行小数运算,否则为整形计算,%操作符必须进行整形运算,得到的余数只能是整形。

 移位操作符

移位操作符是对二进制位进行移位,(int)为32位比特位,(char)为8个比特位...在计算机中变量是以补码形式存放在内存中的。而移位操作是在此基础上进行的。

补充原反补码相关知识:

正数的原、反、补码相同。(为了方便做减法)

无符号数没有原、反、补码。

补码 = 原码取反(反码) +1

反码:除符号位其他位取反

原码 = 补码取反 + 1 or 补码-1再取反

左移操作符

有符号:算数移位,左边丢弃左边补符号位

无符号:逻辑移位,左边丢弃左边补0

这里为了省功夫,我们用字符类型来演示:

char a = 4;00000100//原码
01111100//补码
printf("%d",a<<1);//01111000补码
//打印:00001000 8//原码

 左移本身并没有改变a的值。打印结果显示的是原码的值,而实际各种运算都是对补码进行操作。

右移操作符

有符号:算数右移,右边丢弃左边补符号位

无符号:逻辑右移,右边丢弃,左边补0

归纳:正数补0,负数补1

一样的道理,右移操作符使值减少到了原来的一半,而左移是扩大2倍,原理参考2进制转换成10进制。

 注意:不要移动负数位,这样的结果是未定义的。(a>>-1)

位操作符

操作对象:二进制位的整数

 按位与&

有0为0,全为1才为1

巧记:可以理解成&&操作符,0&&1为1 1&&1为1 

3 & 5//char
//原码
00000011
00000101
//补码
01111101
01111011
01111001 //3&5
//原码输出:00000111//7

 按位或|

有1为1,全为0才为0

巧记:可以理解成||操作符,0||1为1 0||0为0 

按位异或^

相同为0,相异为1

巧记:可以联想哲学道理:世界上没有两片相同的树叶,相同是悖论为0,相异为真理为1。

异或交换数字

有没有一种不需要中间变量就能交换两个数的方法呢?异或或许能做到这一点。

常规做法 

		int a = 3;int b = 5;a = b + a - a;b = b + a - b;

 这种做法可能出现数字大的时候导致溢出,我们可以改进一下:

// 5^5 = 0
// 0^5 = 5
//3^5^5 = 3^0 = 3;	    
int a = 3;
int b = 5;
a = a ^ b;
b = a ^ b;
a = b ^ a;

由于0和任何数异或都为这个数本身(相异),而自己异或自己为0(相同),这使得我们交换数字是存在一种有趣的加密解密效应,但无疑使得代码可读性大大降低,所以一般不推荐这样交换数字。

计算二进制中1的个数

 我们可以使用移位操作符,依次将该数的比特位进行移动,再通过与1按位与进行判断(按位异或也可)。

00000001//1
00010010 >>
00000011 >>

 按位与在遇到1结果为1,遇到0时结果为0,这样能区分0和1,异或也是同理。

	int n = 8;unsigned int sz = sizeof(n);//非负整数int bit_num = sz * 8;//计算比特位int sum = 0;int i = 0;for (i = 0; i < bit_num; i++){if (1 & (n>>i))sum++;}printf("%d\n", sum);// 01000// 00001

结果输出1,记住移位并不会直接改变数字大小,所以得在判断时调整。

关系操作符

> 、==、<、>=、<=像这样的操作符叫做条件操作符。

注意:

关系操作符不能比较两个结构体大小,但可以比较其成员变量的大小。

不能比较两个字符串大小,因为比较的是两个字符串首元素地址。

逻辑操作符

&&和||代表逻辑操作符,对于&&,如果其中一个条件为假,就跳出判断,对于||,如果其中一个条件为真,则跳出判断,这是逻辑操作符的短路与断路现象。

真返回1,假返回0 

条件操作符

exp1?exp2:exp3

三目操作符:真返回第二个表达式,假返回第三个表达式

 逗号表达式

从左往右依次计算,最后一个表达式的值为表达式的结果

    int a = 2;int b = 0;int c = (a > b, a = b + 10, a, b = a + 1);printf("%d %d %d\n", a,b,c);

这个表达式的值为多少呢?

答案是:10 11 11,大家可以自己算算。

	a = get_val();count_val(a);while (a > 0){a = get_val();count_val(a);}

这段代码重复的部分除了可以用do...while循环改写还可以用逗号表达式改写:

while (a = get_val(), count_val(a), a > 0){//业务处理}

将需要先处理的代码用逗号表达式放到while()里,是一种很巧妙的做法。

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

下标引用:[]

函数调用:

void test1(int x, int y)
{}
void test2()
{}
int main()
{test1(3, 4);//操作数(),3,4test2();//操作数()

结构成员

  • 结构体.成员变量
  • 结构体指针->成员变量
struct book
{char name[10];int price;
};
int main()
{struct book s1 = { "wei",30 };struct book* s2 = &s1;//不能为空printf("%s %d\n", s1.name, s1.price);printf("%s %d", s2->name, s2->price);

 隐式类型转换

表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度一般就是int的字节长度,所以当计算对象小于int(4字节)时,会发生整型提升

char a = 5; //00000101
char b = 126;//01111110
char c = a + b;
//整型提升000000000000000000000000000001010000000000000000000000000111111000000000000000000000000010000011

 当把计算的结果存到c中去时,会发生截断,因为char只能存8个字节。

//截断
10000011

输出时发生整型提升:

printf("%d\n", c);//以整形打印10进制//11111111111111111111111110000011(补码)//打印(原码):10000000000000000000000001111101//-125

注:提升时有符号类型补符号位,无符号类型补0。 

截断和提升都是对补码操作。

整形提升实例:

 char a = 0xb6;short b = 0xb600;int c = 0xb6000000;if(a==0xb6)printf("a");if(b==0xb600)printf("b");if(c==0xb6000000)printf("c");
a:1011 0110->11111111111111111111111110110110

只输出结果c,因为a,b发生整形提升,负数取原码后,原来的值也发生了改变。

当用sizeof去对小于4字节的变量进行表达式计算时,自己也会为4字节

 

算术转换

如果某个操作符的各个操作数属于不同类型,就会发生算数转换,算数转换按照如下优先级顺序转换:

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

 当然,如果转换顺序不合理,将会出现精度丢失等情况。

float f = 3.14//float = double
int num = f;//隐式转换

操作符属性

1. 操作符的优先级
2. 操作符的结合性(从左向右、从右向左、无顺序)
3. 是否控制求值顺序(三目操作符、&&、||等)

大家可以自行查表记忆它们的特点和顺序,不需要死记硬背,用到时即可查阅。 

问题表达式

int main()
{int i = 10;i = i-- - --i * ( i = -3 ) * i++ + ++i;printf("i = %d\n", i);return 0;
}

像这样不知道哪一步该执行,不同编译器的处理也是不同的,所以我们书写代码的时候尽量降低复杂性,提高可读性

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/65356.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java并发编程(四)线程同步 中 [AQS/Lock]

概述 Java中可以通过加锁&#xff0c;来保证多个线程访问某一个公共资源时&#xff0c;资源的访问安全性。Java提出了两种方式来加锁 第一种是我们上文提到的通过关键字synchronized加锁&#xff0c;synchronized底层托管给JVM执行的&#xff0c;并且在java 1.6 以后做了很多…

Flink窗口分类简介及示例代码

水善利万物而不争&#xff0c;处众人之所恶&#xff0c;故几于道&#x1f4a6; 文章目录 1. 流式计算2. 窗口3. 窗口的分类◆ 基于时间的窗口&#xff08;时间驱动&#xff09;1) 滚动窗口&#xff08;Tumbling Windows&#xff09;2) 滑动窗口&#xff08;Sliding Windows&…

ArcGIS Maps SDK for JavaScript系列之三:在Vue3中使用ArcGIS API加载三维地球

目录 SceneView类的常用属性SceneView类的常用方法vue3中使用SceneView类创建三维地球项目准备引入ArcGIS API创建Vue组件在OnMounted中调用初始化函数initArcGisMap创建Camera对象Camera的常用属性Camera的常用方法 要在Vue 3中使用ArcGIS API for JavaScript加载和展示三维地…

太牛了!国内版ChatDoc企业知识库,直接操作Doc、Docx、PDF、txt等文件

自ChatGPT问世以来&#xff0c;国外就有ChatPDF、ChatDOC等基于文档问答的项目&#xff0c;但是国内还一直处于对话类产品的研发中。 贵州猿创科技研发了基于本地向量模型的ChatDoc知识库系统&#xff0c;可以直接上传Doc、Docx、PDF、txt、网页链接等进行问答。 体验地址&…

【资讯速递】AI与人类思维的融合;OpenAI在中国申请注册“GPT-5”商标;移动大模型主要面向to B 智能算力是未来方向

2023年8月11日 星期五 癸卯年六月廿五 第000001号 欢迎来到爱书不爱输的程序猿的博客, 本博客致力于知识分享&#xff0c;与更多的人进行学习交流 本文收录于IT资讯速递专栏,本专栏主要用于发布各种IT资讯&#xff0c;为大家可以省时省力的就能阅读和了解到行业的一些新资讯 资…

redis的基础命令01

1、操作库的指令 1、清除当前库---flushdb 2、清除所有库---flushAll 2、操作key的指令 最常用的指令get、set 1&#xff09;set key value 2&#xff09;get key 基础指令 1、del 删除单个&#xff1a;del key 、批量删除&#xff1a;del key1 key2 key3 2、exists 判断key是否…

1.作用域

1.1局部作用域 局部作用域分为函数作用域和块作用域。 1.函数作用域: 在函数内部声明的变量只能在函数内部被访问&#xff0c;外部无法直接访问。 总结&#xff1a; (1)函数内部声明的变量&#xff0c;在函数外部无法被访问 (2)函数的参数也是函数内部的局部变量 (3)不同函数…

Eclipse-配置彩色输出打印

文章目录 前言配置下载查看是否安装 前言 这是一篇古老的文章&#xff0c;那个时候还在用Eclipse &#xff0c;现在已经换 IDEA 了… 这是一篇 2018 年的文章&#xff0c;我只是将文章从个人比较挪到了CSDN 中 配置 配置完然后下载下面插件即可生成彩色代码。 下载 ANSI …

章节5:Burp 扫描功能

章节5&#xff1a;Burp 扫描功能 参考资料 https://portswigger.net/burp/documentation/scanner https://portswigger.net/burp/documentation/desktop/scanning 模块总体介绍&#xff1a; https://portswigger.net/burp/vulnerability-scanner 扫描功能的使用&#xff…

MEC | 条款3 绝对不要以多态(polymorphically)方式处理数组

条款3 绝对不要以多态&#xff08;polymorphically&#xff09;方式处理数组 文章目录 条款3 绝对不要以多态&#xff08;polymorphically&#xff09;方式处理数组继承Example 打印基类-派生类数组传入BalencedBST 数组到函数 删除基类-派生类数组>>>>> 欢迎关…

06 为什么需要多线程;多线程的优缺点;程序 进程 线程之间的关系;进程和线程之间的区别

为什么需要多线程 CPU、内存、IO之间的性能差异巨大多核心CPU的发展线程的本质是增加一个可以执行代码工人 多线程的优点 多个执行流&#xff0c;并行执行。&#xff08;多个工人&#xff0c;干不一样的活&#xff09; 多线程的缺点 上下文切换慢&#xff0c;切换上下文典型值…

MySQL入门学习教程(三)

上一章给大家说的是数据库的视图&#xff0c;存储过程等等操作&#xff0c;这章主要讲索引&#xff0c;以及索引注意事项&#xff0c;如果想看前面的文章&#xff0c;url如下&#xff1a; MYSQL入门全套(第一部)MYSQL入门全套(第二部) 索引简介 索引是对数据库表中一个或多个…