C语言操作符详解 一针见血!

news2024/11/26 12:24:45

目录

  1. 算数操作符

  1. 移位操作符

  1. 位操作符

  1. 赋值操作符

  1. 单目操作符

  1. 关系操作符

  1. 逻辑操作符

  1. 条件操作符

  1. 逗号表达式

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

  1. 表达式求值

11.1 隐式类型转换

  1. 算数操作符

💭 注意

/ 除法 --得到的是商
% 取模(取余)--得到的是余数
如果除法操作符的两个操作数都是整数,执行的是整数除法
如果除法操作符的两个操作数只只要有一个是浮点数,执行的是小数除法
取模操作符两端必须都是整数

例:

int main()
{
    printf("%d\n", 10 / 2);//5
    printf("%d\n", 10 % 2);//0
    printf("%lf\n", 10 / 3.0);//3.333333
    printf("%d\n", 10 / 3);//3
    return 0;
}
  1. 移位操作符

移位操作符移动的是二进制的位。
10进制的数据中:都是0~9的数字组成的。
2进制的数据中:都是0~1的数字组成的。
8进制的数据中:都是0~7的数字组成的。
16进制的数据中:都是0~9 a~f组成的。

数据的二进制表示:

整数的二进制表示形式由3种:原码 反码 补码

注意: 正整数的原码、反码、补码是相同的
负整数的原码、反码、补码要计算
整数在内存中存储的是补码。

原码:把一个数按照正负直接翻译成二进制就是原码

反码:原码符号位不变,其他位按位取反

补码:反码+1

2.1左移操作符 <<

左移一位二进制位(补码),后面空出的一位补0

正数进行左移操作

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

负数进行左移操作:

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

负数的补码和原码不同,所以在进行负数移位时应先求出该数字的补码,之后在补码的基础上进行移位操作。

-3的补码:

补码进行移位操作:

移位后根据移位后的二进制位进行-1取反得到原码,即为我们所求的b

也可以继续取反,+1。

2.2 右移操作符 >>

右移分为两种:

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

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

而右移采用以上哪种,取决于编译器。一般使用算术右移。

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

💭 注意:移位操作不要移动负数位。

  1. 位操作符--位指的是二进制位(补码)

& 按位与

| 按位或

^ 按位异或

💭 注意:这里进行的操作数必须都是整数形式

& 按位与:对应的二进制位进行按位与,有0结果为0,全1结果为1。即相同为1,不同为0。

例:

int main()
{
    int a = 3;
    int b = -5;
    int c = a & b;
    printf("%d\n", c);
    //000000000000000000000000000000011 3的补码
    //100000000000000000000000000000101
    //111111111111111111111111111111010
    //111111111111111111111111111111011 -5的补码
    //000000000000000000000000000000011  3
}

| 按位或:对应的二进制位进行按位或,有1则为1,全0为0。

例:

int main()
{
    int a = 3;
    int b = -5;
    int c = a | b;
    printf("%d\n", c);
    return 0;
    //000000000000000000000000000000011 3的补码
    //111111111111111111111111111111011 -5的补码
    //111111111111111111111111111111011  -5的补码,原码为-5
}

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

例:

int main()
{
    int a = 3;
    int b = -5;
    int c = a ^ b;
    printf("%d\n", c);
    return 0;
    //000000000000000000000000000000011 3的补码
    //111111111111111111111111111111011 -5的补码
    //111111111111111111111111111111000  补码
    //100000000000000000000000000000111  取反
    //100000000000000000000000000001000   加1   -8
}
💭:异或支持交换律和结合律

例1:不创建临时变量实现两个数字交换

int main()
{
    int a = 3;
    int b = 5;
    printf("前%d %d\n", a, b);
    a = a ^ b;
    b = a ^ b;
    a = a ^ b;
    printf("后%d %d\n", a, b);
    return 0;
}

例2:求一个整数存储在内存中的二进制1的个数

int main()
{
    int a = 10;
    int count = 0;
    int i = 0;
    while (i < 32)
    {
        if (a & 1 == 1)
        {
            count++;
        }
        a = a >> 1;
        i++;
    }
    printf("%d\n", count);
    //000000000000000000000000000001010  2
    return 0;
}
  1. 赋值操作符

赋值操作符可以进行连续赋值。

  1. 单目操作符

! 逻辑反操作

& 取地址操作符

sizeof 操作数的类型长度

~ 对二进制位按位取反

-- 前置、后置--

++ 前置、后置++

*间接引用操作符(解引用操作符)

强制类型转换(类型)

~ 对二进制位按位取反

int main()
{
    int a = 0;
    printf("%d\n", ~a);
    //00000000000000000000000000000000
    //11111111111111111111111111111111 
    //11111111111111111111111111111110 
    //10000000000000000000000000000001  -1
    return 0;
}
int main()
{
    int a = 3;
    //000000000000000000000000000011
    //000000000000000000000000001000
    a |= (1 << 3);
    printf("%d\n", a);
    //000000000000000000000000001011
    //111111111111111111111111110111
    a &= (~(1 << 3));
    printf("%d\n", a);
    return 0;
}
  1. 关系操作符

> >= < <= != ==

7.逻辑操作符--只关注真假

&& 逻辑与

|| 逻辑或

&&操作符左边为假右边不再计算
|| 操作符左边为真右边不再计算

8.条件操作符

exp1 ? exp2 : exp3

例:两个表达方式结果是一样的

int main()
{
    int a = 0;
    int b = a ? 1 : 2;
    printf("%d\n", b);
    /*if (a)
    {
        b = 1;
    }
    else
    {
        b = 2;
    }*/
    return 0;
}

9.逗号表达式

exp1 , exp2 , exp3 , .......expn

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

例:

int main()
{
    int a = 1;
    int b = 2;
    int c = (a > b, a = b + 10, b = a + 1);//13
    printf("%d\n", c);
    return 0;
}

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

下标引用:[ ]

int main()
{
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    printf("%d", arr[5]);
    return 0;
}

注意:arr和10是[ ]的操作数

函数调用( )

int main()
{
    int a = strlen("abc");
    printf("%d", a);
    return 0;
}
void test()
{

}
int main()
{
    test();
    return 0;
}

注意:test是()的操作数

访问结构体成员

结构体.成员名

结构体->成员名

struct S
{
    int num;
    char c;
};
int main()
{
    struct S s = { 100,'b' };//结构体的初始化使用{}
    printf("%d\n", s.num);
    printf("%c\n", s.c);
    return 0;
}

注意:.操作符 结构体变量.结构体成员

struct S
{
    int num;
    char c;
};
void test(struct S* ps)
{
    /*printf("%d\n", (*ps).num);
    printf("%c\n", (*ps).c);*/
    printf("%d\n", ps->num);
    printf("%c\n", ps->c);
}
int main()
{
    struct S s = { 100,'b' };//结构体的初始化使用{}
    test(&s);
    return 0;
}

注意:结构体指针->结构体成员

11.表达式求值

表达式求值由操作符的优先级和结合性决定,在一些情况下有些表达式的操作数在求值的过程中可能要转换成其他类型来计算。

11.1隐式类型转换 主要讨论short和char类型

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

什么意思呢?简单来讲,CPU的通用寄存器长度是整型变量的长度也就是4个字节,(为了获得更高的精度)即使是两个char类型的相加,也要先转换为整型int的长度再进行相加。

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

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

如何进行整型提升?

负数的整型提升
char c1=-1;
变量c1的二进制位(补码)有8个比特位 11111111
char为有符号的char
所以整型提升的时候,高位补充符号位,即为1
提升后的结果:
11111111111111111111111111111111
正数的整型提升:
char c2=1;
变量c2的二进制位(补码)有8个比特位 00000001
char为有符号的char
所以整型提升的时候,高位补充符号位,即为 0
提升后的结果:
00000000000000000000000000000001
无符号整型提升,高位补0
int main()
{
    char a = 3;
    //00000000000000000000000000000011
    //00000011 截断
    char b = 127;
    //00000000000000000000000001111111
    //01111111 截断
    char c = a + b;
    //00000000000000000000000000000011
    //00000000000000000000000001111111
    //00000000000000000000000010000010
    //10000010  c 截断
    //整型提升
    printf("%d", c);
    //因为c是char类型的数据所以又要进行整型提升
    // //10000010  有符号数用符号位填充
    //11111111111111111111111100000010   补码
    //10000000000000000000000011111101   取反
    //10000000000000000000000011111110   原码
    return 0;

}
int main()
{
    char c = 1;
    char d = 2;
    printf("%u\n", sizeof(c));//1
    printf("%u\n", sizeof(+c));//4  进行了整型提升
    printf("%u\n", sizeof(-c));//4  进行了整型提升
    printf("%u\n",sizeof(c+d));//4  进行了整型提升
    return 0;
}

11.2算术转换 主要讨论字节大小大于等于int的变量类型

如果某个操作符的各个操作数属于不同类型,除非其中一个操作数转换为另一个操作数的类型,否则操作无法进制,下面层次体系称为寻常算术转换。

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

类型向上转换 例如int 和long int进行表达式求值,将int 转换为long int 进行计算。

复杂表达式的求值有3个影响因素:

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

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

注意控制求值顺序操作符:&& 逻辑与 | |逻辑或 ?:条件操作符 ,逗号表达式控制求值顺序,也就是说可以控制哪些算哪些不算
&&操作符左边为假右边不再计算
|| 操作符左边为真右边不再计算
exp1?exp2:exp3 exp1真则表达式为exp2的值否则为exp3
, 逗号表达式的值为最后一个表达式的值

操作符的属性:

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

函数的调用先后顺序无法通过操作符的优先级决定

int main()
{
    int i = 1;
    int ret = (++i) + (++i) + (++i);
    printf("%d\n", ret);//12
    printf("%d\n", i);//4
    return 0;
}

在我们写代码时,还是希望能够写出能表现出操作符优先顺序的代码。

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

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

相关文章

CentOS 根路径下各个目录的作用及介绍

前言 很多小伙伴刚刚开始接触Linux系统时肯定和我一样&#xff0c;都很懵&#xff0c;黑黢黢的界面&#xff0c;一个个目录&#xff0c;没有图形化界面&#xff0c;看着难受&#xff0c;多接触了一些后会好受一些&#xff0c;不过&#xff0c;对各个目录的了解肯定也很基础&am…

若依框架---PageHelper分页(十)

在前几天的文章中&#xff0c;我们介绍了PageHelper的分页方法&#xff0c;研读代码定位到了ExecutorUtil.pageQuery(...)方法&#xff0c;并阅读到了其中的部分代码。 今天我们将看到重要的SQL修改代码。 getPageSql 我们接着看代码&#xff1a; if (!dialect.beforePage(…

2023爬虫学习笔记 -- 批量爬取图片

一、目标网址http://img.itlun.cn/uploads/allimg/180703/1-1PF3160531-lp.jpg二、右击图片获取图片地址http://img.itlun.cn/uploads/allimg/180703/1-1PF3160531-lp.jpg三、以二进制形式返回响应数据响应requests.get(网页,headers头) 响应内容响应.content四、存储二进制数据…

SpringBoot整合Mybatis的核心原理

0. 前言&#xff1a;1. 自动配置类MybatisAutoConfiguration&#xff1a;1.1. SqlSessionFactory的生成&#xff1a;1.2. Mapper的扫描和代理生成&#xff1a;1.2.1. MapperScannerConfigurer1.2.2. MapperFactoryBean1.2.3. getMapper生成代理对象2. 小结&#xff1a;0. 前言&…

Vue2仿网易云风格音乐播放器(附源码)

Vue2仿网易云风格音乐播放器1、整体效果2、使用技术3、实现内容4、源码5、使用图片1、整体效果 2、使用技术 使用了HTML5 CSS3进行页面布局及美化使用Vue2进行数据渲染与页面交互使用Axios发送http请求获取数据 3、实现内容 实现了搜索歌曲功能&#xff0c;输入歌手或歌曲关…

如果企业遭受到攻击应该进行怎样的处理

声明 本文是学习2018勒索病毒白皮书政企篇. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 政企遭遇勒索攻击分析 由于感染政企客户更有可能获得赎金&#xff0c;再加上勒索病毒本身也以服务器定向攻击为主&#xff0c;所以&#xff0c;2018年政企客…

构建工具tsup入门第三部分

&#x1f384;Hi~ 大家好&#xff0c;我是小鑫同学&#xff0c;一位长期从事前端开发的编程爱好者&#xff0c;我将使用更为实用的案例输出更多的编程知识&#xff0c;同时我信奉分享是成长的唯一捷径&#xff0c;在这里也希望我的每一篇文章都能成为你技术落地的参考~ 目录&am…

“慌不择路”周鸿祎,昔日大炮忙跟风【短评】

文|智能相对论作者| 凯文2月7日下午360经历两次急速拉升后涨停了&#xff0c;作为一个被套牢的股民&#xff0c;我是羡慕的&#xff0c;但理智告诉我&#xff0c;360的后续难以为继。360涨停的原因很简单&#xff0c;只因其在投资者互动平台上对类ChatGPT技术的布局做出了回应&…

安装Sentinel控制台与初始化演示工程

目录 一、Sentinel 二、安装Sentinel控制台 &#xff08;一&#xff09;sentinel组件由2部分构成 &#xff08;二&#xff09;安装步骤 三、初始化演示工程 四、流控模式 &#xff08;一&#xff09;快速失败 &#xff08;二&#xff09;关联资源 &#xff08;三&…

第四章——随机变量的数字特征

文章目录1、数字特征的定义2、数学期望&#xff08;均值&#xff09;2.1、数学期望的定义及性质2.1.1、定义2.1.2、性质2.2、数学期望相关例题2.3、Yg(X)的数学期望2.4、Zg(X,Y)的数学期望2.5、随机变量函数的数学期望例题3、方差3.1、方差的定义与性质3.2、相关例题3.3、切比雪…

3.2 埃尔米特转置

定义 对于复矩阵&#xff0c;转置又不一样&#xff0c;常见的操作是共轭转置&#xff0c;也叫埃尔米特转置Hermitian transpose。埃尔米特转置就是对矩阵先共轭&#xff0c;再转置&#xff0c;一般来说用三种符号表示埃尔米特转置&#xff1a; 第一种符号是AHA^HAH&#xff0c…

热门盘点 | 10款评分最高的项目管理工具

项目管理软件可以让项目经理及时掌握项目进展可把复杂的任务分解简单帮助项目经理及时了解整个团队进展随着现代项目需求日趋复杂和个性选一个好的项目管理软件还是很有必要的① PingCode国内研发项目管理软件PingCode&#xff0c;它是国内软件研发项目榜单中评分最高的项目管理…

达梦实现高可用性的实现(failover功能/负载均衡/虚拟ip透明切换)

达梦实现高可用性的实现&#xff08;failover功能/负载均衡/虚拟ip透明切换&#xff09;一&#xff1a;failover功能&#xff1a;基于守护进程和监视器两个内在工具实现守护进程监视器&#xff1a;数据守护和读写分离集群共享存储集群二&#xff1a;负载均衡&#xff1a;基于jd…

在线支付系列【22】微信支付实战篇之集成服务商API

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 文章目录前言1. 环境搭建2. 特约商户进件3. 统一下单总结前言 在上篇文档中&#xff0c;我们做好了接入前准备工作&#xff0c;接下来使用开源框架集成服务商相关API。 一个简单的支付系统完成支付流程…

火爆全网的ChatGPT使用教程

最近&#xff0c;大家有没有被ChatGPT所刷屏呢&#xff1f;记得之前元宇宙刚出来的时候&#xff0c;也是极其火爆&#xff0c;虽说这二者是不同的性质&#xff0c;但是都是代表着当下互联网发展之迅速。 一、什么是ChatGPT 百度百科中给出的解释&#xff1a;ChatGPT&#xff0…

【Explain详解与索引优化最佳实践】

摘要 explain命令是查看MySQL查询优化器如何执行查询的主要方法&#xff0c;可以很好的分析SQL语句的执行情况。每当遇到执行慢&#xff08;在业务角度&#xff09;的SQL&#xff0c;都可以使用explain检查SQL的执行情况&#xff0c;并根据explain的结果相应的去调优SQL等。 …

LabVIEW中加载.NET 2.0,3.0和3.5程序集

LabVIEW中加载.NET 2.0,3.0和3.5程序集已使用.NETFramework 2.0,3.0或3.5创建了.NET程序集&#xff0c;但是当尝试在构造函数节点中加载这些程序集时&#xff0c;却收到LabVIEW消息显示: 所选文件不是.NET程序集&#xff0c;所属类型库或自动化可执行文件。所以想确认是否可以在…

多线程环境下的伪共享

今天和大家聊一聊伪共享 1.什么是伪共享&#xff1f; 缓存一致性协议在计算机中针对的最小单元&#xff1a;缓存行&#xff0c;每个缓存行的大小是64字节&#xff0c;一串连续的64字节数据都会存储到缓存行中。 假设数据A和数据B在同一缓存行中&#xff0c;CPU1修改了数据A&am…

你每天所做的工作,让你产生了成就感吗?

我们是为了什么而工作&#xff1f;金钱&#xff1f;理想&#xff1f;生活&#xff1f; 似乎这一切都没有标准答案&#xff0c;你自己问你自己&#xff0c;问问你自己&#xff0c;每天踏入公司&#xff0c;坐到工位面前&#xff0c;你最真实的感受是什么&#xff1f; “成就感…

OpenHarmony 3.2 Beta多媒体系列——视频录制

一、简介媒体子系统为开发者提供了媒体相关的很多功能&#xff0c;本文针对其中的视频录制功能做个详细的介绍。首先&#xff0c;我将通过媒体子系统提供的视频录制Test代码作为切入点&#xff0c;给大家梳理一下整个录制的流程。二、目录foundation/multimedia/camera_framewo…