C语言 操作符(下)

文章目录

  • 目录

    文章目录

    前言

    一、移位操作符

    [1.1 左移操作符 <<](#1.1 左移操作符 <<)

    [1.2 右移操作符 >>](#1.2 右移操作符 >>)

    [二、位操作符 :& | ^ ~](#二、位操作符 :& | ^ ~)

    [2.1 按位与操作符 &](#2.1 按位与操作符 &)

    [2.2 按位或操作符 |](#2.2 按位或操作符 |)

    [2.3 按位异或操作符 ^](#2.3 按位异或操作符 ^)

    [2.4 按位取反操作符 ~](#2.4 按位取反操作符 ~)

    三、逗号表达式

    [四、下标引用操作符 [ ]](#四、下标引用操作符 [ ])

    五、函数调用操作符()


    前言

在计算机系统中,数值⼀律⽤补码来表⽰和存储。原因在于,使⽤补码,可以将符号位和数值域统⼀ 处理;同时,加法和减法也可以统⼀处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。那么我们的移位操作符和位操作符都是对数值的二进制补码进行操作的。


一、移位操作符

注意的是:

1. 移位操作符的操作数只能是整数

2. 对于移位运算符,不要移动负数位,这个是标准未定义的。

3. 操作数为两个

1.1 左移操作符 <<

左移操作符移位规则:数值补码左边抛弃、右边补0

如下代码:

cpp 复制代码
#include <stdio.h>
int main()
{
	int num = 10;
	int n = num << 1;
	printf("n = %d\n", n);  //n = 20
	printf("num = %d\n", num);  //num = 10
	return 0;
}

它的左移操作如下图显示:

1.2 右移操作符 >>

右移操作符移位规则:⾸先右移运算分两种:

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

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

我们先看逻辑右移的代码:

cpp 复制代码
#include <stdio.h>
int main()
{
	int num = -1;
	int n = num >> 1;       //逻辑右移情况下:
	printf("n = %d\n", n);                //n = 1
	printf("num = %d\n", num);            //num = -1
	return 0;
}

它的右移操作如下图所示:

再来看看算术右移情况下:

cpp 复制代码
#include <stdio.h>
int main()
{
	int num = -1;
	int n = num >> 1;       //算术右移情况下:
	printf("n = %d\n", n);                //n = -1
	printf("num = %d\n", num);            //num = -1
	return 0;
}

它的右移操作如下图所示:

我们可以看到对于右移操作符我们有两种不同结果,这取决于编译器使用哪种,不过市面上大多数编译器 都支持并且使用算术右移 ,在计算时,我们一般默认算术右移


二、位操作符 :& | ^ ~

注意的是:

1.位操作符的操作数必须是整数。

2.1 按位与操作符 &

操作数为两个

使用规则:两个操作数补码对应上的两个数,只有1跟1与为1,1跟0与为0

代码如下:

cpp 复制代码
#include <stdio.h>
int main()
{
	int num1 = -1;
	int num2 = 3;
	printf("%d\n", num1 & num2);   //3
	return 0;
}

按位与操作如下图:

2.2 按位或操作符 |

操作数为两个

使用规则:两个操作数补码对应上的两个数,1和1、0都为1,两个0才为0

代码如下:

cpp 复制代码
#include <stdio.h>
int main()
{
	int num1 = -1;
	int num2 = 3;
	printf("%d\n", num1 | num2);   //-1
	return 0;
}

按位或操作如下图:

2.3 按位异或操作符 ^

操作数为两个

使用规则:两个操作数补码对应上的两个数,相同为0,不同为1

代码如下:

cpp 复制代码
#include <stdio.h>
int main()
{
	int num1 = -1;
	int num2 = 3;
	printf("%d\n", num1 ^ num2);   //-4
	return 0;
}

按位异或操作如下图:

2.4 按位取反操作符 ~

操作数为一个

使用规则:将操作数的补码全部取反

代码如下:

cpp 复制代码
#include <stdio.h>
int main()
{
	int num2 = -3;
	printf("%d\n", ~num2 );   //2
	return 0;
}

按位取反操作如下图:


三、逗号表达式

逗号表达式,就是⽤逗号隔开的多个表达式并且可能是C语言中最被低估的操作符之一。它的形式为:

cpp 复制代码
exp1, exp2, exp3, ...expN

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

我们用代码练习一下吧,以便加深印象。

cpp 复制代码
#include <stdio.h>
int main()
{
	//代码1
	int a = 1;
	int b = 2;
	int c = (a > b, a = b + 10, a, b = a + 1);//逗号表达式
	//c等于多少呢?
	printf("%d\n", c);
	return 0;
}

在这逗号表达式中,我们从始至终要记住,整个表达式的结果是最后⼀个表达式的结果。

那么我们就可以知道,a>b为假=0,a=b+10为a=12,a=12,b=a+1为b=13,那么整个表达式最后一个结果就是13,所以c=13.


四、下标引用操作符 [ ]

操作数:⼀个数组名+⼀个索引值

cpp 复制代码
#include <stdio.h>
int main()
{
	int arr[10];//创建数组

	arr[9] = 10;//实⽤下标引⽤操作符。[]的两个操作数是arr和9。

	return 0;
}

需要注意的是下标引用操作符的操作数最少为1个,且只能是数组名,如下代码:

cpp 复制代码
#include <stdio.h>
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };//创建数组

	arr[9] = 10;//实⽤下标引⽤操作符。[]的两个操作数是arr和9。

	return 0;
}

五、函数调用操作符()

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

代码如下:

cpp 复制代码
#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;
}

这里要注意的是:函数必须紧跟着函数调用操作符,也可以说函数必须有函数调用操作符。

像sizeof就不是函数,它是一个操作符。

cpp 复制代码
#include <stdio.h>
int main()
{
	int a = 10;

	printf("%d\n", sizeof(a));//别看它紧跟着函数调用操作符,其实不然
	printf("%d\n", sizeof a);  //它可以不跟着的,也就说明了sizeof不是函数,而是一个操作符

	return 0;
}
相关推荐
项目題供诗13 分钟前
C语言基础(三)
c语言·c++
博览鸿蒙17 分钟前
FPGA 开发软件学习笔记分享(内含安装与环境配置)
笔记·学习·fpga开发
码农水水23 分钟前
中国电网Java面试被问:流批一体架构的实现和状态管理
java·c语言·开发语言·面试·职场和发展·架构·kafka
日更嵌入式的打工仔1 小时前
SxsTrace.exe使用笔记
笔记
其美杰布-富贵-李1 小时前
pycalphad 学习笔记
笔记·学习·热力学计算
宵时待雨1 小时前
数据结构(初阶)笔记归纳2:顺序表的实现
c语言·数据结构·笔记·算法
Moonquakes5401 小时前
嵌入式基础学习笔记(51)
笔记·单片机·学习
小鱼23332 小时前
STM32中的中断机制与应用
c语言·stm32·单片机·嵌入式硬件·mcu
宵时待雨2 小时前
STM32笔记归纳1:STM32的基本信息与引脚分布
笔记·stm32·嵌入式硬件
_叶小格_2 小时前
ansible自动化入门基础
运维·笔记·学习·自动化·ansible