【C语言】操作符详解

目录

一、算数操作符

 二、移位操作符

1.左移操作符

2.右移操作符

(1) 逻辑右移

(2) 算术右移

 (3)小总结

三、位操作符

四、赋值操作符

五、单目操作符

六、关系操作符

七、逻辑操作符

八、 条件操作符

九、逗号表达式

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

1. [ ]下标引用操作符

 2.  ( )函数调用操作符

3. 访问一个结构的成员

十一、表达式求值

1.隐式类型转换

2.算术转换 

3.操作符的属性

十二、操作符优先级


一、算数操作符

+    -    *   /   %

  • 除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数
  • 对于 / 操作符如果两个操作数都为整数,执行整数除法。但是,只要有浮点数参与运算就是浮点数除法
  • % 要求两个操作数必须为整数,得到的是余数

 二、移位操作符

>>        右移操作符

<<        左移操作符

注意:移位操作符的操作数只能是整数

1.左移操作符

规则巧记:左边抛弃,右边补0

这里假设存的是 int n =15;的二进制 进行左移 n<<1; 如果n 在没有被左移赋值的情况下,n自身的值是不会发生变化。(这里与自增自减不一样)

在深层次看一下,一个数 n<<1,  发现相当于该数 n * 2^1。n << 2;   等于 n * 2^2 

2.右移操作符

(1) 逻辑右移

移位规则:右边舍弃,左边补0

假设内存 存放的是 -1 补码的二进制   

(2) 算术右移

移位规则:右边舍弃,左边用原值的符号位进行填充

 

 (3)小总结

如果 算术右移与 逻辑右移 总是分不清。巧记:(算术右移,可以想象成 算数,既然算数肯定会有正负,进而想到 左边填充的是原符号位)

注意:对于位操作符,不存在移动负数位,C语言标准并未规定

int num = 10;

num>> -1;  //error(不要多次一举)

num  << 1;  // ok  右移  -1  这不相当于 左移 1 嘛。

三、位操作符

&        //按位与  巧记:有0则0,其中  一个数 a&1 可求 该数的每一个二进制位

|         //按位或   巧记:有1则1

^        //按位异或 巧记:相同为0,相异为1

注:操作数必须是整数

【例】1

#include<stdio.h>int main() 
{int a = 1;//0001int b = 2;//0010/** a& b;* 0001* 0010* 0000* * a|b* 0001* 0010* 0011* * a^b* 0001* 0010* 1100*/return 0;
}

接下来看一道面试题

【例】2 不能创建临时变量(第三变量),实现两个数的交换

解法一:

两个数进行来回加减来进行两个数的交换,通过调试的监视的窗口我们可以看到两个数的交换 

 解法二:

#include<stdio.h>
int main()
{int a = 10;int b = 20;a = a ^ b;b = a ^ b;a = a ^ b;printf("%d %d",a,b);return 0;
}

从打印结果可以看到a 与 b的值进行了交换

【解析】^ 按位异或 相同为0,相异为1(可以理解为 相同假,相异为真)

前面,提到 可以用a&1 该数的每一个二进制位,看下方例题

【例】编写代码,求一个整数存储在内存中的二进制中1的个数

#include<stdio.h>
int main()
{int n = 10;int count = 0;//  0000 1010//  0000 0001int i = 0;for (i = 0; i < 32;i++){if (n & 1 == 1){count++;}		n = n>>1;}printf("%d",count);return 0;
}

 这里用到了 >> 和 ^

解法二:

#include<stdio.h>
int main()
{int n = 10;int count = 0;while (n) {if (n%2 == 1){count++;}n /= 2;}return 0;
}

这里的思路是 因为计算机存储是二进制 0 和1 ,%2取余判断是否为1,/2进行下一位 

 解法三:

#include<stdio.h>
int main()
{int n = -1;int i = 0;int count = 0;while (n){count++;n = n & (n - 1);//1111 1111 1111 1111 1111 1111 1111 1111//1111 1111 1111 1111 1111 1111 1111 1110//1111 1111 1111 1111 1111 1111 1111 1110}printf("%d ", count);return 0;
}

这里的优化 是借助 两个数差1 进行按位与,一个一个位找1

四、赋值操作符

 =  这是赋值符,不是等于!!!

赋值操作符  给一个变量进行赋值 注意赋值操作符的优先级比较低(包括复合赋值符)

int age = 18;age = 20;  //对变量进行赋值

赋值操作符支持连续使用;

int a = 0;
int b = 10;
int c = 1;
a = b = c+1;  //这里是连续赋值

虽然可以连续赋值,但是代码的可读会下降

b = c+1;
a = b;
//这样子是不是看着更用以理解

代码的可读性也是很重要的

接下来看复合赋值符都有哪些

+= 、-=、*= 、/= 、%= 、>>=  、<<= 、&= 、 |= 、^=

int a = 10;
a = a+10;
//可以写成这样
a += 10;

其他复合赋值符同上方用法一致

五、单目操作符

单目操作符就是操作数只有一个

 sizeof ()括号里面不是类型时可以省略(),说到sizeof ,其中 size_t 是一种类型,是一种无符号整型的,size_t 就是为sizeof专门设计的一种类型,打印时使用%zd,但是size_t 在不同平台下可能是 unsigned int   也有可能是  unsigned long long int 

sizeof(数组名) ,计算的是整个数组的大小

++前置,先对该数+1,然后再去使用这个数

++后置,相当于 先使用该数,然后在对该数进行 +1

-- 与上方的++同理

六、关系操作符

> 、 >= 、 < 、 <=  、!= 、==

注意:== 这个是 等于

            =   这个是 赋值

七、逻辑操作符

&&        逻辑与

||           逻辑或

要区分

& 与 &&   ;   | 与 ||

1&2   --->  0  

1&&2  --->  1   (左边为假,右边无需计算,直接为假)

1  |  2 --->  3

1  ||  2 ---> 1 (左边为真,右边无需计算,直接为真)

【例】1笔试题,求结果输出的值

#include<stdio.h>
int main()
{int i = 0, a = 0, b = 2, c = 3, d = 4;i = a++ && ++b && d++;printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);return 0;
}

  【结果】a = 1 b = 2 c = 3 d = 4

解析    首先 a = 0 ,a++ ,是先使用后 +1,又有&& (左边为假,右边无需计算,直接为假)

打印的是 a  = 1,其他值正常打印

【例】2 对这个题进行改编 a = 1

#include<stdio.h>
int main()
{int i = 0, a = 1, b = 2, c = 3, d = 4;i = a++ && ++b && d++;printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);return 0;
}

【结果】 a = 2 b = 3 c = 3 d = 5

解析  a = 1时,左边为真,后面表达式继续进行计算,进而 a = 2, b = 3,c =3 ,d= 5

【例】3 对这个题进行改编 && 改为 ||  , 并求出i 的值

#include<stdio.h>
int main()
{int i = 0, a = 0, b = 2, c = 3, d = 4;i = a++ || ++b || d++;printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);return 0;
}

【结果】 a = 1 b = 3 c = 3 d = 4  i = 1

解析 因为时逻辑或 (左边为真,右边无需计算,直接为真)虽然先使用 a 为假,但接下来的操作数 ++b , b = 3为真 进而后面无需计算。而 i 表达式里面有真 则 i = 1, 为真

八、 条件操作符

表达式1 ?表达式2 :表达式3;

唯一 一个三目操作符

在这里 看一个 求最大值的代码

 a>b?a:b; //中文解释 a>b 吗?大于就是a, 不大于就是b

【例】求三个数的最大值 

#include<stdio.h>
int main() 
{int a = 1;int b = 2;int c = 3;int max = 0;max = a > b ? a : b;max = max > c ? max : c;printf("%d",max);return 0;
}

 这里是使用两次条件操作符进行计算三个数中的最大值

九、逗号表达式

表达式1 , 表达式2 ,... , 表达式n

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

//代码1
int a = 1;
int b = 2;
int c = (a>b, a=b+10, a, b=a+1);//逗号表达式

c 的结果是 13

逗号表达式可以对代码进行优化

a = get_val();
count_val(a);
while (a > 0)
{//业务处理a = get_val();count_val(a);
}//使用逗号表达式可以改写为
while (a = get_val(), count_val(a), a > 0)
{//业务处理
}

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

1. [ ]下标引用操作符

注意 操作数为 一个数组名 + 一个索引值

int arr[20]; //创建数组
// [ ] 的操作数 是 arr  和 20

 2.  ( )函数调用操作符

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

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

3. 访问一个结构的成员

.        结构体.成员名

->      结构体指针 -> 成员名

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

十一、表达式求值

表达式求值的顺序一部分是由操作符的 优先级结合性 决定。
同样,有些表达式的操作数在求值的过程中可能需要转换为其他类型。

1.隐式类型转换

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

整型提升的意义

表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度
一般就是int的字节长度,同时也是CPU的通用寄存器的长度。因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长度。

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

//例
char a,b,c;
a = b + c;

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

整型提升

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

char c1 = -1;
变量c1的二进制位(补码)中只有8个比特位:
1111111
因为 char 为有符号的 char
所以整形提升的时候,高位补充符号位,即为1
提升之后的结果是:
11111111111111111111111111111111
//正数的整形提升
char c2 = 1;
变量c2的二进制位(补码)中只有8个比特位:
00000001
因为 char 为有符号的 char
所以整形提升的时候,高位补充符号位,即为0
提升之后的结果是:
00000000000000000000000000000001

无符号整形提升,高位补0

【例】1

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;
}

【结果】c

实例的a,b要进行整型提升,但是c不需要整形提升a,b整形提升之后,变成了负数,所以表达式 a==0xb6 , b==0xb600 的结果是假,但是c不发生整形提升,则表达式 c==0xb6000000 的结果是真.

【a】1101 0110  整型提升1111 1111 1111 1111 1111 1111 1101 0110

【b】1101 0110 0000 0000 整型提升1111 1111 1111 1111 1101 0110 0000 0000

【例】2

int main()
{char c = 1;printf("%u\n", sizeof(c));printf("%u\n", sizeof(+c));printf("%u\n", sizeof(-c));return 0;
}

【结果】1 4 4

实例2中的,c只要参与表达式运算,就会发生整型提升,表达式 +c ,就会发生提升,所以 sizeof(+c) 是4个字节。表达式 -c 也会发生整形提升,所以 sizeof(-c) 是4个字节,但是 sizeof(c) ,就是1个字节

2.算术转换 

如果某个操作符的 各个操作数的类型不一样,那么除非其中一个操作数的转换为另一个操作数的类型,否则操作就无法进行。下面 寻常算术转换

long double

double

unsigned long int 

long int

unsigned int

int

向上转换  如果某个操作数的类型在上面这个列表中排名较低,那么首先要转换为另外一个操作数的类型后执行运算

注意: 算数转换要合理,否则可能会出现精度丢失
 

float pi = 3.14;​​​​​​​int num = f;//num = 3 精度丢失

3.操作符的属性

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

  • 操作符的优先级
  • 操作符的结合性
  • 是否控制求值顺序

两个相邻的操作符先执行哪个?取决于他们的优先级。如果两者的优先级相同,取决于他们的结合性。

十二、操作符优先级

点击下方链接查看​​​​​​​

链接:操作符优先级

注意:我们写出的表达式如果不能通过操作符的属性确定唯一的计算路径,那这个表达式就是存在问题的。

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

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

相关文章

GO学习之 微框架(Gin)

GO系列 1、GO学习之Hello World 2、GO学习之入门语法 3、GO学习之切片操作 4、GO学习之 Map 操作 5、GO学习之 结构体 操作 6、GO学习之 通道(Channel) 7、GO学习之 多线程(goroutine) 8、GO学习之 函数(Function) 9、GO学习之 接口(Interface) 10、GO学习之 网络通信(Net/Htt…

UDS的DID(Data identification)

引言 DID是UDS中的一个重要概念&#xff0c;它代表着特定的数据标识符。DID用于标识和获取ECU中的特定参数数据&#xff0c;如传感器数据、状态信息等。通过使用DID&#xff0c;诊断工具可以准确地获取所需的数据&#xff0c;从而帮助诊断人员更好地了解车辆的状态和性能。 D…

开发者必知:.gitignore 文件的魔法,助你管理项目文件如虎添翼!

前言&#xff1a; 在软件开发的世界中&#xff0c;版本控制是一个至关重要的环节。而 Git 作为目前最流行的分布式版本控制系统之一&#xff0c;已经成为开发者不可或缺的工具。然而&#xff0c;在日常的开发过程中&#xff0c;有些文件是不适合被纳入版本控制的&#xff0c;比…

基于Java+SpringBoot+Vue的数码论坛系统设计与实现(源码+LW+部署文档等)

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架…

【C语言】深度剖析数据在内存中的存储

一、数据类型详细介绍 1、数据类型介绍 &#xff08;1&#xff09;基本的内置类型 //内置类型就是C语言自带的类型char //字符数据类型 short //短整型 int //整形 long //长整型 long long //更长的整形 float //单精度浮点数 double …

安防监控视频汇聚平台EasyCVR分发的FLV视频流在VLC中无法播放是什么原因?

众所周知&#xff0c;TSINGSEE青犀视频汇聚平台EasyCVR可支持多协议方式接入&#xff0c;包括主流标准协议国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。在视频流的处理与分发上&#xff0c;视频监控…

ORACLE行转列、列转行实现方式及案例

ORACLE行转列、列转行实现方式及案例 行转列案例方式1.PIVOT方式2.MAX和DECODE方式3.CASE WHEN和GROUP BY 列转行案例方式1.UNPIVOT方式2.UNION ALL 行转列 案例 假设我们有一个名为sales的表&#xff0c;其中包含了产品销售数据。表中有三列&#xff1a;product&#xff08;…

FPGA实践 ——Verilog基本实验步骤演示

0x00 回顾&#xff1a;AND/OR/NOT 逻辑的特性 AND&#xff1a;与门可以具有两个或更多的输入&#xff0c;并返回一个输出。当所有输入值都为 1 时&#xff0c;输出值为 1。如果输入值中有任何一个为 0&#xff0c;则输出值为 0。 OR&#xff1a;或门可以具有两个或更多的输入…

【python】-【】

文章目录 转义字符和原字符二进制与字符编码标识符和保留字变量的定义和使用变量字符串列表for 一、print会输出①数字②字符串&#xff08;必须加引号&#xff09;③含有运算符的表达式&#xff08;例如 31 其中3&#xff0c;1是操作数&#xff0c;是运算符&#xff09;&#…

vector的模拟实现

什么是vector vector是一个封装了动态大小数组的顺序容器跟任意其它类型容器一样&#xff0c;它能够存放各种类型的对象。 模拟实现 实现前的准备 在实现vector之前&#xff0c;为了和库里的区分开需要将实现的vector放在一个自定义的命名空间里。而且vector需要实现成模版…

论文阅读 - Neutral bots probe political bias on social media

论文链接&#xff1a;Neutral bots probe political bias on social media | EndNote Click 试图遏制滥用行为和错误信息的社交媒体平台被指责存在政治偏见。我们部署中立的社交机器人&#xff0c;它们开始关注 Twitter 上的不同新闻源&#xff0c;并跟踪它们以探究平台机制与用…

超导热催生meme,换汤不换药的投机轮回

文/章鱼哥 出品/陀螺财经 币圈对炒作meme概念的热情从未消亡过。 随着一种名为LK-99的物质被发现&#xff0c;围绕超导的兴奋不仅激发了科学界&#xff0c;加密货币相关概念也与之沸腾。不出所料&#xff0c;与此前围绕元宇宙、AI大肆炒作一样&#xff0c;许多meme代币已经出现…

关于MySQL中的binlog

介绍 undo log 和 redo log是由Inno DB存储引擎生成的。 在MySQL服务器架构中&#xff0c;分为三层&#xff1a;连接层、服务层&#xff08;server层&#xff09;、执行层&#xff08;存储引擎层&#xff09; bin log 是 binary log的缩写&#xff0c;即二进制日志。 MySQL…

android开发之Android 自定义滑动解锁View

自定义滑动解锁View 需求如下&#xff1a; 近期需要做一个类似屏幕滑动解锁的功能&#xff0c;右划开始&#xff0c;左划暂停。 需求效果图如下 实现效果展示 自定义view如下 /** Desc 自定义滑动解锁View Author ZY Mail sunnyfor98gmail.com Date 2021/5/17 11:52 *…

数据结构——线性表

文章目录 线性表的定义和基本操作顺序表线性表的链式表示 线性表的定义和基本操作 线性表是具有相同数据类型的(n≥0)个数据元素的有限序列&#xff0c;其中n为表长&#xff0c;当n0时线性表是一个空表。若用L命名线性表&#xff0c;则其中一般表示为&#xff1a;L(a1,a2,a3, …

CCLINK转MODBUS-TCP网关cclink通讯接线图 终端电阻

大家好&#xff0c;今天我们要聊的是生产管理系统中的CCLINK和MODBUS-TCP协议&#xff0c;它们的不同使得数据互通比较困难&#xff0c;但捷米JM-CCLK-TCP网关的出现改变了这一切。 1捷米JM-CCLK-TCP是一款自主研发的CCLINK从站功能的通讯网关&#xff0c;它的主要功能是将各种…

D455+VINS-Fusion+surfelmapping 稠密建图(三)

继续&#xff0c;由surfelmapping建立的点云生成octomap八叉树栅格地图 一、安装OctomapServer 建图包 安装插件 sudo apt-get install ros-melodic-octomap-ros sudo apt-get install ros-melodic-octomap-msgs sudo apt-get install ros-melodic-octomap-server sudo apt-…

cubemx hal stm32 舵机 可减速 任意位置停止 驱动代码

CubeMX配置 对于 STM32 F407VE 这里的84是来自APB1那路2倍频得到&#xff1a; 代码部分 两个舵机都是180度的 servo.c #include "servo.h" #include "tim.h" #include "stdio.h"__IO uint32_t g_SteerUWT[2] {0}; uint16_t g_SteerDeg[…

青大数据结构【2014】

一、单选 二、简答 为了解决顺序队列的假溢出问题&#xff0c;提出了循环队列&#xff0c;即把存储队列的表从逻辑上看成一个环 判别队列空和满有三种方法&#xff1a; 1&#xff09;采用计数器判别&#xff0c;空时&#xff0c;计数器为0&#xff1b;满时&#xff0c;计数器…

【设计模式——学习笔记】23种设计模式——中介者模式Mediator(原理讲解+应用场景介绍+案例介绍+Java代码实现)

文章目录 案例引入案例一普通实现中介者模式 案例二 介绍基础介绍登场角色尚硅谷 《图解设计模式》 案例实现案例一&#xff1a;智能家庭类图实现 案例二&#xff1a;登录页面逻辑实现说明类图实现 总结文章说明 案例引入 案例一 普通实现 在租房过程中&#xff0c;客户可能…