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

【C语言操作符详解(一)】--进制转换,原反补码,移位操作符,位操作符,逗号表达式,下标访问及函数调用操作符

目录

一.操作符的分类

二.二进制和进制转换

2.1--2进制转10进制

​编辑 2.1.1--10进制转2进制数字

2.2--2进制转8进制和16进制 

2.2.1--2进制转8进制

2.2.2--2进制转16进制 

三.原码,反码,补码

四.移位操作符

4.1--左移操作符

4.2--右移操作符

五.位操作符:&,|,^,~

5.1--位操作符的理解与使用

5.2--相关练习

5.2.1--练习1:不能创建临时变量(第三个变量),实现两个整数的交换。

5.2.2--练习2:编写代码实现:求一个整数存储在内存中的二进制中1的个数

5.2.3--练习3:二进制位置0或者置1

六.逗号表达式,下标访问 [],函数调用 ()

6.1--逗号表达式

6.2--[] 下标引用操作符

6.3--() 函数调用操作符


前言:上篇文章我们学习了函数递归的相关知识,今天我们将继续操作符的详解学习的第一部分,让大家对于c语言的操作符产生一些新的认识和想法。


一.操作符的分类

1.算术操作符:+ , - , * ,  / , %

2.移位操作符:<< , >>

3.位操作符:&, | ,^

4.赋值运算符:= , += ,- = ,*= ,/= ,%= ,<<=  ,>>= ,  &= ,  |=  ,^=

5.单目操作符:!,++ ,- - ,& ,* ,+(正),-(负) ,~ ,sizeof ,(类型)

6.关系操作符:> ,>= ,< ,<= ,== ,!= 

7.逻辑操作符:&& ,|| ,!

8.条件操作符:exp1?exp2:exp3

9.逗号表达式:,

10.下标引用:【】

11.函数调用:()

12.结构成员访问:.   , ->

上述的操作符中,有部分在之前的学习中有提到过,今天继续介绍一部分,其中有部分操作符和二进制有关系,我们先来学习一下二进制和进制转换的相关知识;


二.二进制和进制转换

2.1--2进制转10进制

--其实10进制的123表示的值是一百二十三,为什么是个值呢?其实10进制的每一位都是有权重的,进制的数字从右向左是个位,十位,百位……,分别每一位的权重是10^0,10^1,10^3;

如下图:

2进制和10进制是类似的,只不过2进制的每一位的权重,从右向左是:2^0,2^1,2^2……

如果是2机制的1101,该怎么理解呢?

 2.1.1--10进制转2进制数字

简单的10进制数字可以直接通过凑的方法来转2进制;

2.2--2进制转8进制和16进制 

2.2.1--2进制转8进制

--8进制的每一位是0~7的,0~7的数字,各自写成2进制,最多有3个2进制位就足够了,比如7的二进制是111,所以2进制转8进制的时候,从2进制序中右边低位开始向左每3个二进制位会换算一个8进制位,剩余不够3个2进制位的直接换算。

如:2进制的01101011,换成8进制:0153,8进制表示的时候前面加0;0开头的数字,会被当作8进制。

2.2.2--2进制转16进制 

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

如:2进制的01101011,换成16进制:0x6b,16进制表示的时候前面加0x


三.原码,反码,补码

--整数2进制的表示方法有三种,即原码,反码和补码(32位)

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

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

负整数的三种表示方法各不相同,变换方式如下。

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

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

补码:反码+1就得到补码。

补码反过来得到原码也是可以使用:取反,+1的操作

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

这是为什么呢?

--在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理(CPU只有加法器)此外,补码和原码相互转换,其运算过程是相同的,不需要额外的硬件电路。


四.移位操作符

<< 左移操作符 

>> 右移操作符

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

4.1--左移操作符

--移位规则:左边抛弃,右边补0;

int num=10;左移一位演示

4.2--右移操作符

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

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

--是逻辑右移还是算术右移取决于编译器,VS2022中采用的是算术右移。

int num=-1;逻辑右移一位演示

int num=-1;算术右移一位演示

注意:对于移位运算符,不要移动负数位,这个是标准没定义的。


五.位操作符:&,|,^,~

5.1--位操作符的理解与使用

位操作符有:

&      //按位与
|      //按位或
^      //按位异或
~      //按位取反

注意:他们的操作数必须是整数。 

我们可以通过一串代码直观了解一下这几个位操作符,注意看注释,来理解是如何使用的。

#include <stdio.h>
int main()
{int num1 = -3;int num2 = 5;
// &--按位与--对应的二进制位进行与运算,只要有0则为0,两个同时为1,才为1printf("%d\n", num1 & num2);
// |--按位或--对应的二进制位进行或运算,只要有1则为1,两个同时为0,才为0printf("%d\n", num1 | num2);
// ^--按位异或--对应的二进制位相同为0,相异为1printf("%d\n", num1 ^ num2);
// ~--按位取反--二进制位0变为1,1变为0printf("%d\n", ~0);return 0;
}

5.2--相关练习

5.2.1--练习1:不能创建临时变量(第三个变量),实现两个整数的交换。

int main()
{int a = 0;int b = 0;printf("请输入两个整数:");scanf("%d %d", &a, &b);printf("交换前:a=%d b=%d\n", a, b);a = a ^ b;// a'=a^b;b = b ^ a;// b=b^a'=b^a^b=a;a = a ^ b;// a=a'^b=a^b^a=b;printf("交换后:a=%d b=%d\n", a, b);return 0;
}

在这里补充两个重要结论:

a ^ a = 0;
a ^ 0 = a;
//且异或支持交换律;
//如:3 ^ 6 ^ 6 = 3
//    6 ^ 3 ^ 6 = 3

5.2.2--练习2:编写代码实现:求一个整数存储在内存中的二进制中1的个数


int count_bits1_of_n(int n)
{//int count = 0;//for (int i = 0;i < 32;i++)//{//	if(((n >> i) & 1)==1)//	count++;//}//return count;//优化方案int count = 0;while (n){n = n & (n - 1);
//用一次这个公式就相当于将一个1变为0,即去掉一个1,当n为0时,1全部去掉,且刚好循环结束count++;}
}int main()
{int n = 0;scanf("%d", &n);int ret = count_bits1_of_n(n);printf("%d", ret);return 0;
}

注意:n=n&(n-1)这个公式的用法在这里很重要。

5.2.3--练习3:二进制位置0或者置1

编写代码将13二进制序列的第五位修改为1,然后再改回0;

int main()
{int a = 13;a = a | (1 << 4);printf("a=%d\n", a);a &= ~(1 << 4);printf("a=%d\n", a);return 0;
}

六.逗号表达式,下标访问 [],函数调用 ()

6.1--逗号表达式

exp1, exp2, exp3, …expN

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

//代码1
int a = 1;
int b = 2;
int c = (a>b, a=b+10, a, b=a+1);//逗号表达式
c是多少?--c是13;//代码2
if(a = b + 1,c = a / 2,d > 0)//代码3
a = get_val();
count_val(a);
while (a > 0)
{//业务处理//...a = get_val();count_val(a);
}如果使⽤逗号表达式,改写:
while (a = get_val(), count_val(a), a>0)
{//业务处理
}

6.2--[] 下标引用操作符

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

int arr[10]={0};//创建数组
arr[9] = 10;//运⽤下标引⽤操作符。
[ ]的两个操作数是arr和9。

6.3--() 函数调用操作符

int Add(int x,int y)
{return x + y;
}int main()
{printf("hehe");//()是函数调用操作符int r = Add(3,5);//()是函数调用操作符// ()也是有操作数:函数名和参数都是()的操作数//()最少有一个操作数,就是函数名本身return 0;
}

结语:操作符详解的第一部分就到此结束了,在下一篇文章中我将继续为大家分享操作符详解的一些其他知识点,感谢大家的支持!

相关文章:

  • 《代码整洁之道》全书归纳
  • SpringMVC 通过ajax 前后端数据交互
  • Scala集合操作与WordCount案例实战总结
  • Linux命令-iostat
  • w~嵌入式C语言~合集6
  • Spring中生成Bean的方式总结-笔记
  • 颠覆传统微商!开源AI智能名片链动2+1模式S2B2C商城小程序:重构社交电商的“降维打击”革命
  • 基于Playwright的浏览器自动化MCP服务
  • Go 语言 核心知识点
  • golang goroutine(协程)和 channel(管道) 案例解析
  • go语言八股文(四)
  • Apache Sqoop数据采集问题
  • 【Spring Boot】Maven中引入 springboot 相关依赖的方式
  • 大模型——Suna集成浏览器操作与数据分析的智能代理
  • [Vulfocus解题系列]Apache HugeGraph JWT Token硬编码导致权限绕过(CVE-2024-43441)
  • Apache Tomcat 漏洞(CVE-2025-24813)导致服务器面临 RCE 风险
  • vue项目页面适配
  • 数据结构【堆和链式结构】
  • PWN基础-利用格式化字符串漏洞泄露canary结合栈溢出getshell
  • 耳机,三段式, 四段式,录音,播放
  • 2025上海体育消费节启动,多形式联动打造体育消费盛宴
  • 新华社评论员:汇聚起工人阶级和广大劳动群众的磅礴力量
  • 西班牙遭遇史上最严重停电,已进入国家紧急状态
  • 夜读丨怀念那个写信的年代
  • 物业也能成为居家养老“服务员”,上海多区将开展“物业+养老”试点
  • 全国电影工作会:聚焦扩大电影国际交流合作,提升全球影响力