如何详细解释各种操作符的功能和用法?

2026-04-12 04:252阅读0评论SEO资讯
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计3223个文字,预计阅读时间需要13分钟。

如何详细解释各种操作符的功能和用法?

在前面+这里的内容自然有不少,不过整体较为简洁。我总结了一些相对有难度的知识点。

操作符+C语言的操作符种类繁多,这里把常见的一些和大家进行一下分析。

算术操作符+移除

写在前面

这里的内容虽然有些多,不过整体较为简单,我总结了一些相对有些难度的的知识点。

操作符

C语言的操作符有很种,这里我把常见的一些和大家进行分析一下.

  • 算术操作符
  • 移位操作符
  • 位操作符
  • 赋值操作符

算术操作符

所谓的算数操作符就是我们的加减乘除,没有什么可以谈的.

+ - * / %

我在这里就谈谈 % 这个操作符,这个操作符是我们取余数的操作,有点意思.

int main() { int num = 11; int ret = num % 10; printf("%d\n", ret); return 0; }

注意,只有整数可以取余.

int main() { double num = 11.0; double ret = num % 10; printf("%lf\n", ret); return 0; }

移位操作符

在谈下面几个操作符时,我先说一下数据在内存中的存储形式,我们知道数据可以用三种二进制方式进行表示,其中补码是计算机的存储方式,毕竟我们数据存在负数,关于原反补三个是如何计算的,我们这里不谈.移位操作符分为下面的两种.

  • 左移
  • 右移

左移

注意左移操作符不是向左移动,准确的说应该是向高位移动,只不过我们平常喜欢把高位放在左边,故我们称之为左移.那么请问当我们左移之后,要知道类型的比特位数是固定的,那么最右边的空位我们因该如何做?这空缺位补0,某种意义上移动一位相当于数据翻倍.

#include<stdio.h> int main() { int a = 5; int b = a << 1; printf("%d\n", b); printf("%d\n", a); return 0; }

右移

右移是向低位移动.右移分为逻辑右移和算术右移.

  • 逻辑右移 二进制向右移动 空缺位补 0
  • 算术右移 二进制向右移动 空缺位补 符号位

对于正数来说,右移时逻辑右移还是算术右移都一样,但是负数就不一样了,

大多数编译器支持算术右移,下面我们看看VS系列怎么样

#include<stdio.h> int main() { int a = -5; int b = a >> 1; printf("%d\n", b); printf("%d\n", a); return 0; }

位操作符

位操作符能够直接改变数字的二进制,下面我就以两个例题来总结位操作符的用法,注意,他们的操作数必须是整数。

  • 按位与 &
  • 按位或 |
  • 按位异或 ^
  • 按位取反 ~
如何判断一个数是不是2的n次幂,我们看看下面数的特点

你会发现,凡是2的n次幂的数 ,他的二进制一定只有一个数字为 1 (这里不考虑负数),那么这就带来一种思路,我们是否可以通过位操作符进行判断,

#include<stdio.h> int main() { int n = 0; scanf("%d", &n); // n-1 一定会拿掉那个唯一的 1 的 if ((n & (n - 1)) == 0) { printf("YES\n"); } return 0; }

交换a,b,不出现第三个变量,这里直接就给思路了 我们发现 n ^ n ==0 , n ^ 0 == n 看下面代码

#include<stdio.h> int main() { int a = 10; int b = 20; printf("Before a = %d b = %d\n", a, b); a = a ^ b; b = a ^ b; //把 b 赋给 a a = a ^ b; //把 a 赋给 b printf("After a = %d b = %d\n", a, b); return 0; }

赋值操作符

这里的赋值操作符就是 = 比较简单,这里就提一下 允许连续赋值

#include<stdio.h> int main() { int a = 0; int b = 0; a = b = 5; //我们不建议 代码风格不好 printf("%d %d", a, b); return 0; }

操作符优先级

注意,操作符的优先级是会影响我们的我们代码的,如果操作符的优先级记忆错了那么有可能会带来很大的影响.不过我们不谈,与其我们背诵操作符的优先级不如我们多多使用括号,这样逻辑还清晰,而且不容易出错.

取整方式

我们都知道 5 / 2 = 2,这是我们记住的,那么我们想过没有,为什么结果是2呢?有人可能这样想在数学中 5 / 2 = 2.5,结果是要求是整型,去尾,所以是2.那为什么不是四舍五入得到 3 呢?这是编译器不同的取整方式造成的.下面我们谈谈取整的几种方式.

零向取整

零向取整 , 本质是向0靠近,不一定是四舍五入,否则-2应该是-3.

#include<stdio.h> int main() { int a = 2.9; int b = -2.9; printf("%d\n", a); printf("%d\n", b); return 0; }

这也解决了 为何5 / 2 结果是2的问题,C语言默认采用零向取整.这里有一个函数,支持零向取整.

#include<stdio.h> #include<math.h> int main() { printf("%d\n", (int)trunc(2.9)); printf("%d\n", (int)trunc(-2.9)); return 0; }

地板取整

所谓的地板取整就是向负无穷取整.

如果我想要它像负无穷取整的话.这里也是通过一个函数来实现.

#include <stdio.h> #include <math.h> //因为使用了floor函数,需要添加该头文件 int main() { //本质是向-∞取整,注意输出格式要不然看不到结果 printf("%.1f\n", floor(-2.9)); //-3 printf("%.1f\n", floor(-2.1)); //-3 printf("%.1f\n", floor(2.9)); //2 printf("%.1f\n", floor(2.1)); //2 return 0; }

向+∞取整

这个和上面恰好相反.

相关的函数如下.

#include <stdio.h> #include <math.h> int main() { //本质是向+∞取整,注意输出格式要不然看不到结果 printf("%.1f\n", ceil(-2.9)); //-2 printf("%.1f\n", ceil(-2.1)); //-2 printf("%.1f\n", ceil(2.9)); //3 printf("%.1f\n", ceil(2.1)); //3 return 0; }

四舍五入取整

我们来到了我们最熟悉的的取整方式了.这里是round函数.

#include <stdio.h> #include <math.h> int main() { //本质是四舍五入 printf("%.1f\n", round(2.1)); printf("%.1f\n", round(2.9)); printf("%.1f\n", round(-2.1)); printf("%.1f\n", round(-2.9)); return 0; }

取模

下面我们说一下是什么是取模?

如果a和d是两个自然数,d非零,可以证明存在两个唯一的整数 q 和 r,满足 a = q*d + r 且0 ≤ r < d.其中,q被称为商,r 被称为余数.

正数取模

这里很简单,我们一眼就可以看出了,重点放在负数上面,他们的一些总结是可以用在这里的.

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

负数取模

这里才是我们的大头,我们试试不同的编译环境然后仔细分析一下我们该如何做.

#include <stdio.h> #include <math.h> int main() { int a = -10; int d = 3; //printf("%d\n", a/d); //C语言中是-3,很好理解 printf("%d\n", a % d); return 0; }

我们把这个代码在不同的环境下跑一遍,先看现象,再来和大家分析.

我们不是说余数大于0吗?是不是定义错了.实际上因为在C语言中,现在-10%3出现了负数,根据定义:满足 a = q\*d + r 且0 ≤ r < d,C语言中的余数,是不满足定义的,因为,r<0了.故,大家对取模有了一个修订版的定义:

如果a和d是两个自然数,d非零,可以证明存在两个唯一的整数 q 和 r,满足 a = q*d + r , q 为整数,且0 ≤ |r|< |d|.其中,q 被称为商,r 被称为余数.

那么在Python中呢?这里的结果是什么样的呢?

这里我们就疑惑,好像出现了矛盾,实际上不是的,这是我们不同语言默认的取整的方式不同, Python采用向-∞取整

这里我们给出一个结论,方式决定商,商决定余数

下面我们继续说一下,我们有的时候把取模也称之为取余,这里还是有一定的区别的.

如何详细解释各种操作符的功能和用法?

  • 取余:尽可能让商,进行向0取整.
  • 取模:尽可能让商,向-∞方向取整

提升与截断

我们之前谈到变量的创建是要在内存中开辟空间的。空间的大小是根据不同的类型而决定的。可是我们看一下下面的代码.

int main() { int a = 10; char ch = 'a'; int x = ch; // 疑问1 ch = a; // 疑问2 return 0; }

这里面我们有两个疑问,我们之前说了不同类型的变量的空间大小是不一样的,我们的int是4字节,char类型是1个字节,请问他们是如何可以相互赋值的?这里就不得谈两个话题,一个是整形提升,一个是截断问题.

数据存储

谈一个耳熟能详的知识点,在计算机中我们存储的数据是补码,这一点我暂时认为大家非常了解,当然如果不太熟悉,可以去看后面的博客.

整型提升

由于CPU以四个字节计算速度快,所以在小于四个字节的的整形数据进行计算时,计算机隐形的将数据提升为四个字节,也就是补足32个比特位,下面是补全的规则.

  • 无符号前面补 0
  • 有符号前面补符号位

下面我分别举一些例子和大家分享.

//输出什么 #include <stdio.h> int main() { char a = -1; signed char b = -1; unsigned char c = -1; printf("a=%d,b=%d,c=%d",a,b,c); return 0; }

截断问题

所谓的数据截断就是我们把大空间的赋值给小空间的,编译器会自动的截断,把相应空间的数据给赋值过去,看代码.

#include <stdio.h> int main() { char a = -128; printf("%u\n",a); return 0; }

标签:内容虽然

本文共计3223个文字,预计阅读时间需要13分钟。

如何详细解释各种操作符的功能和用法?

在前面+这里的内容自然有不少,不过整体较为简洁。我总结了一些相对有难度的知识点。

操作符+C语言的操作符种类繁多,这里把常见的一些和大家进行一下分析。

算术操作符+移除

写在前面

这里的内容虽然有些多,不过整体较为简单,我总结了一些相对有些难度的的知识点。

操作符

C语言的操作符有很种,这里我把常见的一些和大家进行分析一下.

  • 算术操作符
  • 移位操作符
  • 位操作符
  • 赋值操作符

算术操作符

所谓的算数操作符就是我们的加减乘除,没有什么可以谈的.

+ - * / %

我在这里就谈谈 % 这个操作符,这个操作符是我们取余数的操作,有点意思.

int main() { int num = 11; int ret = num % 10; printf("%d\n", ret); return 0; }

注意,只有整数可以取余.

int main() { double num = 11.0; double ret = num % 10; printf("%lf\n", ret); return 0; }

移位操作符

在谈下面几个操作符时,我先说一下数据在内存中的存储形式,我们知道数据可以用三种二进制方式进行表示,其中补码是计算机的存储方式,毕竟我们数据存在负数,关于原反补三个是如何计算的,我们这里不谈.移位操作符分为下面的两种.

  • 左移
  • 右移

左移

注意左移操作符不是向左移动,准确的说应该是向高位移动,只不过我们平常喜欢把高位放在左边,故我们称之为左移.那么请问当我们左移之后,要知道类型的比特位数是固定的,那么最右边的空位我们因该如何做?这空缺位补0,某种意义上移动一位相当于数据翻倍.

#include<stdio.h> int main() { int a = 5; int b = a << 1; printf("%d\n", b); printf("%d\n", a); return 0; }

右移

右移是向低位移动.右移分为逻辑右移和算术右移.

  • 逻辑右移 二进制向右移动 空缺位补 0
  • 算术右移 二进制向右移动 空缺位补 符号位

对于正数来说,右移时逻辑右移还是算术右移都一样,但是负数就不一样了,

大多数编译器支持算术右移,下面我们看看VS系列怎么样

#include<stdio.h> int main() { int a = -5; int b = a >> 1; printf("%d\n", b); printf("%d\n", a); return 0; }

位操作符

位操作符能够直接改变数字的二进制,下面我就以两个例题来总结位操作符的用法,注意,他们的操作数必须是整数。

  • 按位与 &
  • 按位或 |
  • 按位异或 ^
  • 按位取反 ~
如何判断一个数是不是2的n次幂,我们看看下面数的特点

你会发现,凡是2的n次幂的数 ,他的二进制一定只有一个数字为 1 (这里不考虑负数),那么这就带来一种思路,我们是否可以通过位操作符进行判断,

#include<stdio.h> int main() { int n = 0; scanf("%d", &n); // n-1 一定会拿掉那个唯一的 1 的 if ((n & (n - 1)) == 0) { printf("YES\n"); } return 0; }

交换a,b,不出现第三个变量,这里直接就给思路了 我们发现 n ^ n ==0 , n ^ 0 == n 看下面代码

#include<stdio.h> int main() { int a = 10; int b = 20; printf("Before a = %d b = %d\n", a, b); a = a ^ b; b = a ^ b; //把 b 赋给 a a = a ^ b; //把 a 赋给 b printf("After a = %d b = %d\n", a, b); return 0; }

赋值操作符

这里的赋值操作符就是 = 比较简单,这里就提一下 允许连续赋值

#include<stdio.h> int main() { int a = 0; int b = 0; a = b = 5; //我们不建议 代码风格不好 printf("%d %d", a, b); return 0; }

操作符优先级

注意,操作符的优先级是会影响我们的我们代码的,如果操作符的优先级记忆错了那么有可能会带来很大的影响.不过我们不谈,与其我们背诵操作符的优先级不如我们多多使用括号,这样逻辑还清晰,而且不容易出错.

取整方式

我们都知道 5 / 2 = 2,这是我们记住的,那么我们想过没有,为什么结果是2呢?有人可能这样想在数学中 5 / 2 = 2.5,结果是要求是整型,去尾,所以是2.那为什么不是四舍五入得到 3 呢?这是编译器不同的取整方式造成的.下面我们谈谈取整的几种方式.

零向取整

零向取整 , 本质是向0靠近,不一定是四舍五入,否则-2应该是-3.

#include<stdio.h> int main() { int a = 2.9; int b = -2.9; printf("%d\n", a); printf("%d\n", b); return 0; }

这也解决了 为何5 / 2 结果是2的问题,C语言默认采用零向取整.这里有一个函数,支持零向取整.

#include<stdio.h> #include<math.h> int main() { printf("%d\n", (int)trunc(2.9)); printf("%d\n", (int)trunc(-2.9)); return 0; }

地板取整

所谓的地板取整就是向负无穷取整.

如果我想要它像负无穷取整的话.这里也是通过一个函数来实现.

#include <stdio.h> #include <math.h> //因为使用了floor函数,需要添加该头文件 int main() { //本质是向-∞取整,注意输出格式要不然看不到结果 printf("%.1f\n", floor(-2.9)); //-3 printf("%.1f\n", floor(-2.1)); //-3 printf("%.1f\n", floor(2.9)); //2 printf("%.1f\n", floor(2.1)); //2 return 0; }

向+∞取整

这个和上面恰好相反.

相关的函数如下.

#include <stdio.h> #include <math.h> int main() { //本质是向+∞取整,注意输出格式要不然看不到结果 printf("%.1f\n", ceil(-2.9)); //-2 printf("%.1f\n", ceil(-2.1)); //-2 printf("%.1f\n", ceil(2.9)); //3 printf("%.1f\n", ceil(2.1)); //3 return 0; }

四舍五入取整

我们来到了我们最熟悉的的取整方式了.这里是round函数.

#include <stdio.h> #include <math.h> int main() { //本质是四舍五入 printf("%.1f\n", round(2.1)); printf("%.1f\n", round(2.9)); printf("%.1f\n", round(-2.1)); printf("%.1f\n", round(-2.9)); return 0; }

取模

下面我们说一下是什么是取模?

如果a和d是两个自然数,d非零,可以证明存在两个唯一的整数 q 和 r,满足 a = q*d + r 且0 ≤ r < d.其中,q被称为商,r 被称为余数.

正数取模

这里很简单,我们一眼就可以看出了,重点放在负数上面,他们的一些总结是可以用在这里的.

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

负数取模

这里才是我们的大头,我们试试不同的编译环境然后仔细分析一下我们该如何做.

#include <stdio.h> #include <math.h> int main() { int a = -10; int d = 3; //printf("%d\n", a/d); //C语言中是-3,很好理解 printf("%d\n", a % d); return 0; }

我们把这个代码在不同的环境下跑一遍,先看现象,再来和大家分析.

我们不是说余数大于0吗?是不是定义错了.实际上因为在C语言中,现在-10%3出现了负数,根据定义:满足 a = q\*d + r 且0 ≤ r < d,C语言中的余数,是不满足定义的,因为,r<0了.故,大家对取模有了一个修订版的定义:

如果a和d是两个自然数,d非零,可以证明存在两个唯一的整数 q 和 r,满足 a = q*d + r , q 为整数,且0 ≤ |r|< |d|.其中,q 被称为商,r 被称为余数.

那么在Python中呢?这里的结果是什么样的呢?

这里我们就疑惑,好像出现了矛盾,实际上不是的,这是我们不同语言默认的取整的方式不同, Python采用向-∞取整

这里我们给出一个结论,方式决定商,商决定余数

下面我们继续说一下,我们有的时候把取模也称之为取余,这里还是有一定的区别的.

如何详细解释各种操作符的功能和用法?

  • 取余:尽可能让商,进行向0取整.
  • 取模:尽可能让商,向-∞方向取整

提升与截断

我们之前谈到变量的创建是要在内存中开辟空间的。空间的大小是根据不同的类型而决定的。可是我们看一下下面的代码.

int main() { int a = 10; char ch = 'a'; int x = ch; // 疑问1 ch = a; // 疑问2 return 0; }

这里面我们有两个疑问,我们之前说了不同类型的变量的空间大小是不一样的,我们的int是4字节,char类型是1个字节,请问他们是如何可以相互赋值的?这里就不得谈两个话题,一个是整形提升,一个是截断问题.

数据存储

谈一个耳熟能详的知识点,在计算机中我们存储的数据是补码,这一点我暂时认为大家非常了解,当然如果不太熟悉,可以去看后面的博客.

整型提升

由于CPU以四个字节计算速度快,所以在小于四个字节的的整形数据进行计算时,计算机隐形的将数据提升为四个字节,也就是补足32个比特位,下面是补全的规则.

  • 无符号前面补 0
  • 有符号前面补符号位

下面我分别举一些例子和大家分享.

//输出什么 #include <stdio.h> int main() { char a = -1; signed char b = -1; unsigned char c = -1; printf("a=%d,b=%d,c=%d",a,b,c); return 0; }

截断问题

所谓的数据截断就是我们把大空间的赋值给小空间的,编译器会自动的截断,把相应空间的数据给赋值过去,看代码.

#include <stdio.h> int main() { char a = -128; printf("%u\n",a); return 0; }

标签:内容虽然