【C操作符】详解操作符

news2025/3/1 11:49:06

操作符

  • 前言
  • 一、操作符分类
  • 二、算数操作符
  • 三、移位操作符
    • (一)原码、补码、反码
    • (二)操作符应用
      • 1.左移操作符
        • (1)正数
        • (2)负数
        • (3)总结
      • 2.右移操作符
        • (1)简单介绍(-1的补码)
        • (2)算术右移
        • (3)逻辑右移
        • (4)警告
        • (5)编译器移位运算
  • 四、位操作符
    • (一)概念
    • (二)按位与
    • (三)按位或
    • (四)按位异或
    • (五)小练习
      • 1.题目描述
      • 2.解题过程
      • 3.代码
      • 4.弊端
  • 五、赋值操作符
    • (一)概念
    • (二)复合赋值符
  • 六、单目操作符
    • (一)介绍
      • 1.引言
      • 2.汇总
      • 3.逻辑反操作
        • (1)概念
        • (2)小知识(布尔类型)
      • 4.负值和正值操作符
        • (1)概念
        • (2)unsigned类型
      • 5.取地址和解引用操作符
        • (1)取地址
        • (2)配合使用
      • 6.sizeof操作符
        • (1)简单了解
        • (2)sizeof的特点
      • 7.二进制按位取反操作符
        • (1)概念:所有位按位取反,但只针对整数。
        • (2)综合应用
      • 8.前置++(- -)和后置++(- -)
        • (1)简单认识
        • (2)传参
      • 9.强制类型转换
    • (二)sizeof与数组
  • 七、关系操作符
  • 八、逻辑操作符
    • (一)概念
    • (二)逻辑与
    • (三)逻辑或
    • (四)综合应用
      • 1.判断闰年
      • 2.面试题
  • 九、条件操作符
  • 十、逗号表达式
  • 十一、下标引用、函数调用和结构成员
    • (一)[]下标引用操作符
    • (二)()函数调用操作符
    • (三)访问一个结构的成员
      • 1.概念
      • 2.例子
  • 十二、表达式求值
    • (一)隐式类型转换
      • 1.整型提升的意义
      • 2.如何进行整型提升
        • (1)截断
        • (2)整型提升
          • (i)正数
          • (ii)负数
          • (iii)小知识
        • (3)代码汇总
      • 3.例子
        • (1)练习1
        • (2)练习2
    • (二)算术转换
    • (三)操作符的属性
      • 1.概念
      • 2.一些问题表达式
        • (1)典例1
        • (2)典例2
        • (3)典例3
        • (4)典例4
  • 总结


前言

操作符可以说是家家必备但不怎么重视的一个C语言武器,那今天我就详细讲一讲C语言当中的操作符,让大家能够很好的理解操作符并运用它们。


一、操作符分类

算数操作符、移位操作符、位操作符、赋值操作符、单目操作符、关系操作符、逻辑操作符、条件操作符、逗号表达式、下标引用、结构调用和结构成员


二、算数操作符

操作符:+ - * / %
1.对于%操作符之外,其他的几个操作符可以作用于整数和浮点数。
2.对于/操作符如果两个操作数都为整数,执行整数除法,而只要有浮点数执行的就是浮点数除法。
3.%操作符的两个操作数必须为整数,返回的是整除之后的余数。
在这里插入图片描述
在这里插入图片描述


三、移位操作符

在这里插入图片描述

(一)原码、补码、反码

#include<stdio.h>

//2进制
//整数的2进制的表现形式,其实有三种
//原码、补码、反码
//在计算机内,内存中存储的是补码的二进制
//所以在参与移位的时候,移动的都是补码
//12 - 数值
//2进制:1100
//8进制:14
//16进制:c
//

int main() {
	//按照一个数的正和负直接写出它的二进制表示形式得到的就是原码
	// 
	//正数的原码、补码、反码是相同的
	//负数的原码、补码、反码需要进行计算
	//负数反码 - 原码的符号位不变,其他位按位取反
	//负数补码 - 反码+1/原码的符号位不变,从右往左找第一个1,这些位不变,其余位取反
	//
	//整形占4个字节(32个比特位)
	//a - 00000000000000000000000000001010 - 原码
	//a - 00000000000000000000000000001010 - 补码
	//a - 00000000000000000000000000001010 - 反码
	int a = 10;

	//b - 10000000000000000000000000001010 - 原码
	//b - 11111111111111111111111111110101 - 反码
	//b - 11111111111111111111111111110110 - 补码
	int b = -10;

	
	return 0;
}

操作符的左右移移动的都是补码的二进制,因为计算机内存中存储的就是补码的二进制。关于原码、补码、反码的知识,在程序注释行里解释过了,大家要仔细看看并理解理解。
大家可以根据下面这张图来理解一下原码、补码和反码。
在这里插入图片描述

(二)操作符应用

1.左移操作符

(1)正数

计算规则:左边丢弃,右边补0。
在这里插入图片描述

在这里插入图片描述

(2)负数

计算规则与正数一样。
在这里插入图片描述
在这里插入图片描述

(3)总结

1.左移操作符左移1位是原本的值进行平方操作。
2.左移后那个最左边的数就是符号位,即使是0,最后结果也是0。
3.计算规则:最高位舍弃,新的第一位做符号位,末位补0。

2.右移操作符

(1)简单介绍(-1的补码)

大家可以进入调试窗口看一看内存分布,发现-1是在内存中存储的是32个1,而展现在我们面前的是16进制数,是因为方便好看。

在这里插入图片描述
而当再考虑补几的时候犹豫了,到底补1呢还是补0呢?这就牵扯到算术右移与逻辑右移了!
在这里插入图片描述
在这里插入图片描述

(2)算术右移

右边丢弃,左边补原本符号位,原本符号位是什么,左边就补充什么符号位。
在这里插入图片描述

(3)逻辑右移

右边丢弃,左边补0。
在这里插入图片描述

(4)警告

移动只能移动正数哦!!!不可以移动负数,这个标准是未定义的。

(5)编译器移位运算

所以编译器到底是算术还是逻辑右移呢?我们打印出来看看!!!
原来是算术右移,因为还是个负数!!!
在这里插入图片描述


四、位操作符

(一)概念

在这里插入图片描述

(二)按位与

规则:按二进制位与,有零则为零,两个同时为1才为1。

//按二进制与
//有零则为零,两个同时为1才为1
//

#include<stdio.h>

int main() {
	int a = 3;
	//00000000000000000000000000000011 - 原码、补码、反码
	int b = -5;
	//10000000000000000000000000000101 - 原码
	//11111111111111111111111111111010 - 反码
	//11111111111111111111111111111011 - 补码
	int c = a & b;
	//a - 00000000000000000000000000000011
	//b - 11111111111111111111111111111011
	//a&b 00000000000000000000000000000011
	//
	printf("%d\n", c);//3
	
	
	return 0;
}

在这里插入图片描述

(三)按位或

规则:按二进制或,对应的二进制位有1则为1,两个同时为0则为0。

//
//按位或 - 有1则为1,俩零才为零
#include<stdio.h>

int main() {
	int a = 3;
	//00000000000000000000000000000011 - 原码、补码、反码
	int b = -5;
	//10000000000000000000000000000101 - 原码
	//11111111111111111111111111111010 - 反码
	//11111111111111111111111111111011 - 补码
	int c = a | b;
	//a - 00000000000000000000000000000011
	//b - 11111111111111111111111111111011
	//a|b 11111111111111111111111111111011
	//
	printf("%d\n", c);//-5


	return 0;
}

在这里插入图片描述

(四)按位异或

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

//
//按位异或 - 相同为0,相异为1
//
#include<stdio.h>

int main() {
	int a = 3;
	//00000000000000000000000000000011 - 原码、补码、反码
	int b = -5;
	//10000000000000000000000000000101 - 原码
	//11111111111111111111111111111010 - 反码
	//11111111111111111111111111111011 - 补码
	int c = a ^ b;
	//a - 00000000000000000000000000000011
	//b - 11111111111111111111111111111011
	//a^b 11111111111111111111111111111000 - 补码
	//    11111111111111111111111111110111 - -1操作
	//    10000000000000000000000000001000 - 取反(原码)
	//    -8
	printf("%d\n", c);//-8

	return 0;
}

在这里插入图片描述

(五)小练习

1.题目描述

不创建临时变量(第三个变量),实现两个整数的交换。

2.解题过程

先来个比较能想到的代码:

//局限性:a,b如果为一个很大的数,两者相加溢出了
#include<stdio.h>

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

这种代码有局限性,如果两个数都很大,相加导致溢出的现象怎么办呢?接下来就需要异或这操作符的辅助了!

异或操作符注意项:在这里插入图片描述
在这里插入图片描述

3.代码

#include<stdio.h>

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

4.弊端

1.效率较低,不如使用临时变量的方法
2.可读性差
3.异或只能针对整数的操作


五、赋值操作符

(一)概念

赋值操作符可以让你得到一个你之前不满意的值,你可以给自己的值进行重新赋值。可以连续赋值,但不是很清晰明了,不利于调试,可读性也较差,尽量使用单句赋值语句,不要一个语句多个赋值操作符。并且,一定要给变量进行初始化赋值,不赋值是很危险的,这个涉及到了函数栈帧的创建与销毁,大家可以看看这篇博客:
函数栈帧的创建与销毁
例如:

int main() {
	int weight = 70;
	weight = 90;//不满意就赋值
	double salary = 10000.9;
	salary = 20000.1;//使用赋值操作符进行赋值
	
	return 0;
}

(二)复合赋值符

在这里插入图片描述

//复合赋值符

int main() {
	int a = 10;
	//a=a+5;
	a += 5;

	int b = 12;
	//b = b >> 1;
	b >>= 1;
	
	return 0;
}

更加简化清晰明了。


六、单目操作符

(一)介绍

1.引言

在这里插入图片描述

2.汇总

在这里插入图片描述

3.逻辑反操作

(1)概念

#include<stdio.h>

int main(){
	//C语言中,0表示假,非零表示真
	int flag = 5;
	//if (flag) { //flag如果为真,做……
	//	printf("hehe\n");
	//}

	if (!flag) { //非flag,!操作符是把假变成真,真变成假
		printf("hehe\n");
	}

	return 0;
}

(2)小知识(布尔类型)

true - 1(非零,负数也算)
falise - 0
在这里插入图片描述
举例(判断闰年):

#include<stdio.h>
#include<stdbool.h>

_Bool is_leap_year(int y) {
	if ((y % 4 == 0) && (y % 100 != 0) || (y % 400 == 0)) {
		return true;
	}
	else {
		return false;
	}
}

int main() {
	int y = 0;
	scanf("%d", &y);
	_Bool ret = is_leap_year(y);
	if (ret) {
		printf("yes\n");
	}
	else {
		printf("no\n");
	}

	return 0;
}

4.负值和正值操作符

(1)概念

正值操作符一般没什么用,一般省略,负值操作符是可以改变值的正负的。
在这里插入图片描述

(2)unsigned类型

概念:把内存中的补码拿出来进行计算!!!

计算器呼出按键:先打开管理,再输入calc。
在这里插入图片描述
在这里插入图片描述

5.取地址和解引用操作符

(1)取地址

只要是个变量就可取地址,例如可以&a,但不能&3。

int main() {
	int a = 10;
	//取出的是内存的地址,可存起来也可打印
	printf("%p\n", &a);
	int* pa = &a;
	
	char ch = 'a';
	char* pc = &ch;

	char arr[10] = { 0 };
	char* arr1 = arr;
	char* p1 = &arr[0];

	char* p = "abcdef";

	return 0;
}

(2)配合使用

在这里插入图片描述
&操作符拿到地址,*操作符解引用去找到它进行操作。

6.sizeof操作符

既是关键字,也是操作符!!!

(1)简单了解

#include<stdio.h>

//函数调用的时候,要写()
//sizeof后边的括号可以省略,说明它是操作符不是函数

int main() {
	int a = 10;
	printf("%d\n", sizeof(a));
	printf("%d\n", sizeof a);//ok

	printf("%d\n", sizeof(int));
	//printf("%d\n", sizeof int);//error 类型名括号不能省略

	int arr[10] = { 0 };
	printf("%d\n", sizeof(arr));//40,计算的是整个数组的字节大小
	printf("%d\n", sizeof(int[10]));//ok
	
	return 0;
}

(2)sizeof的特点

可以打断运算!!!
在这里插入图片描述
原因:
文件在进行操作的时候,是通过编译,链接到test.exe,而sizeof很强大,在编译期间就已经打断赋值运算了,根据的是原本变量的类型大小进行输出的。
在这里插入图片描述

7.二进制按位取反操作符

(1)概念:所有位按位取反,但只针对整数。

#include<stdio.h>
//~按位取反,只针对整数

int main() {
	int a = 0;
	printf("%d\n", ~a);
	//00000000000000000000000000000000
	//11111111111111111111111111111111 - 按位取反
	//10000000000000000000000000000000 - 反码
	//10000000000000000000000000000001 - 补码
	//-1
	return 0;
}

(2)综合应用

按位与、按位或、按位取反的综合应用。

#include<stdio.h>

int main() {
	int a = 9;
	//00000000000000000000000000001001
	//00000000000000000000000000010000  |操作   1<<4
	//00000000000000000000000000011001
	//
	//把a的二进制中的第五位改成1
	a |= (1 << 4);
	printf("%d\n", a);

	//把a的二进制中的第五位改成0
	//00000000000000000000000000011001
	//11111111111111111111111111101111   &操作   ~(1<<4)
	//00000000000000000000000000001001
	a &= ~(1 << 4);
	printf("%d\n", a);
	return 0;
}

在这里插入图片描述

8.前置++(- -)和后置++(- -)

(1)简单认识

举例:
在这里插入图片描述
在这里插入图片描述

(2)传参

在这里插入图片描述
注意:++和–是带有副作用的,它会影响自己。
比如:b=++a后,a的值会自增1;b=a+1后,a的值不会自增1。

9.强制类型转换

当迫不得已的时候,可以进行强制类型转换。
在这里插入图片描述

(二)sizeof与数组

这里sizeof操作符单独拿出来讲,说明sizeof的重要性。

#include<stdio.h>

void test1(int arr[]) {
	printf("%zd\n", sizeof(arr));
}

void test2(char ch[]) {
	printf("%zd\n", sizeof(ch));
}

int main() {
	int arr[10] = { 0 };
	char ch[10] = { 0 };
	printf("%zd\n", sizeof(arr));
	printf("%zd\n", sizeof(ch));
	test1(arr);
	test2(ch);
	
	return 0;
}

在这里插入图片描述


七、关系操作符

在这里插入图片描述


八、逻辑操作符

(一)概念

在这里插入图片描述
大家看这个肯定很熟悉,我们之前讲过的按位与和按位或,这个不就是双倍吗!但大家要注意的是按位与和按位或是通过二进制计算的,而逻辑与和逻辑或只关注真和假。

(二)逻辑与

两个同是真为真,只要有假即为假。
在这里插入图片描述
在这里插入图片描述

(三)逻辑或

两个同是为假则为假,有一个真就是真。
在这里插入图片描述
在这里插入图片描述

(四)综合应用

1.判断闰年

//判断闰年:
//1.能被4整除但不能被100整除
//2.能被400整除
#include<stdio.h>

int main() {
	int year = 2000;
	if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) {
		printf("yes\n");
	}

	return 0;
}

2.面试题

复合++和–和&&和||的操作。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


九、条件操作符

表达式1的结果如果为真,则计算表达式2,不计算表达式3。
表达式1的结果如果为假,则计算表达式3,不计算表达式2。
也被称为三目操作符。
在这里插入图片描述
例如:
在这里插入图片描述


十、逗号表达式

在这里插入图片描述
逗号表达式就是用逗号隔开的多个表达式。
逗号表达式,从左往右依次进行,整个表达式的结果是最后一个表达式的结果。
在这里插入图片描述
在这里插入图片描述


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

(一)[]下标引用操作符

操作符:一个数组名+一个索引值
在这里插入图片描述

(二)()函数调用操作符

接受一个或者多个操作符:第一个操作符是函数名,剩余的操作数就是传递给函数的参数。
函数调用的时候至少要有一个操作数。
在这里插入图片描述

(三)访问一个结构的成员

1.概念

在这里插入图片描述

//char int float double long long short - 内置类型
//自定义类型 - 结构体、枚举、联合体
//结构体 - 自定义类型(聚合类型)
//生活中有些对象要被描述的话,不能简单的使用单个内置类型
//描述一本书:书名+定价+作者+出版社…… - 结构体(struct)来聚合它们

#include<stdio.h>

//类型
struct book {
	char name[20];
	int price;
	char author[20];
};

void Print(struct book* b1) {
	//结构体变量.成员名
	printf("%s %d %s\n", (*b1).name, (*b1).price, (*b1).author);
}

void Print1(struct book* b2) {
	//结构体指针->成员名
	printf("%s %d %s\n", b2->name, b2->price, b2->author);//指向成员
}

int main() {
	struct book b1 = { "cpp",10,"renhai" };//初始化
	struct book b2 = { "cppp",20,"jiang" };//初始化
	printf("%s %d %s\n", b1.name, b1.price, b1.author);
	printf("%s %d %s\n", b2.name, b2.price, b2.author);
	//结构体变量.成员名

	//分装函数
	Print(&b1);
	Print1(&b2);
	return 0;
}

2.例子

仅仅是值传参上去是改变不了值的,而传地址上去才能改变值的大小。

#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);
	printf("%d\n", stu.age);//20

	pStu->age = 20;//结构成员访问
	set_age2(pStu);
	printf("%d\n", stu.age);//18

	return 0;
}

十二、表达式求值

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

(一)隐式类型转换

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

1.整型提升的意义

表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度一般就是int的字节长度,同时也是CPU的通用寄存器的长度。
因此,即使两个char类型的值进行相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长度。
通用CPU(general-purpose CPU)是难以直接实现两个8比特字节直接相加运算(虽然机器指令中可能有这种字节相加指令)。所以,表达式中各种长度可能小于int长度的整型值,都必须先转换为int或者unsigned int,然后才能送入CPU去执行相应的运算。

2.如何进行整型提升

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

(1)截断

当赋值操作符右边是整数,是有32个比特位的,而char类型只能存放一个字节,也就是8个字节,所以发生截断,只保留低八位。
在这里插入图片描述

(2)整型提升

(i)正数

当截断完要进行整数相加的操作之前,a(正数)和b(正数)进行整数提升,也就是在高处补0,再进行计算
在这里插入图片描述

(ii)负数

当要整型提升的那个数是负数的时候,即高位是1的时候,在前面补1,补1之后得到的数是二进制的补码,因为这是在计算机内部进行操作的,计算机内部存储的是二进制的补码,所以是补码,而想要打印出来,就需要有符号的数转换到原码进行打印。
在这里插入图片描述

(iii)小知识

关于char的无符号和有符号的数的范围:
在这里插入图片描述
解析如下:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

(3)代码汇总

//char short int long……
// 1     2    4    
int main() {
	//signed char的取值范围是-128 - 127
	//unsigned char的取值范围是0 - 255
	//
	//char =signed char 是有符号位的
	char a = 3;
	//截断 - 4个比特位的空间放到1个比特位的空间里(长的变成短的)
	//00000000000000000000000000000011 - 原码
	//char只有一个字节,也就是8个比特位,所以a里面存放的是:00000011

	char b = 127;
	//00000000000000000000000001111111 - 原码
	//b - 01111111

	char c = a + b;
	//00000011
	//01111111
	//整型提升 - 正数整型提升高位补0
	//整型提升 - char类型整型提升到int类型(短的变成长的)
	//00000000000000000000000000000011
	//00000000000000000000000001111111
	//00000000000000000000000010000010
	//放到c里面去,只能存8个比特位 - 10000010 - c
	printf("%d\n", c);
	//%d 是打印十进制的整数
	//整型提升 - 负数整型提升高位补1
	//10000010 - c
	//11111111111111111111111110000010 - 补码
	//10000000000000000000000001111110 - 原码 - -126

	return 0;
}

3.例子

(1)练习1

#include<stdio.h>

int main()
{
	char a = 0xb6;
	short b = 0xb600;
	int c = 0xb6000000;

	//a发生整型提升
	//0xb6 - 10110110 - 182
	//a整型提升后 - 11111111111111111111111110110110 - 补码
	//              10000000000000000000000001001010 - 原码 -74
	if (a == 0xb6)  //进入不了
		printf("a");
	//同理b也发生整型提升
	if (b == 0xb600)//进入不了
		printf("b");
	//c不发生整型提升
	if (c == 0xb6000000) //可以进入
		printf("c");
	return 0;
}

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

在这里插入图片描述

(2)练习2

#include<stdio.h>

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

c只要参与表达式运算,就会发生整形提升,表达式 +c ,就会发生提升,所以 sizeof(+c) 是4个字节,表达式 -c 也会发生整形提升,所以 sizeof(-c) 是4个字节,但是 sizeof© ,就是1个字节。
在这里插入图片描述

(二)算术转换

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

根据字节大小进行排名(从高往下递减):
在这里插入图片描述
解释:不同类型的数相加,需要转化为字节更大的那个数再进行相加。即:如果int类型的数加上double类型的数,那编译器会先把int类型的数转换为double类型的字节长度并进行计算(就高不就低)。

但同样有小问题,如果float类型转换为int类型是能转换的,但是存在精度丢失的问题。

(三)操作符的属性

1.概念

复杂表达式的求值有三个影响的因素:
1.操作符的优先级
2.操作符的结合性
3.是否控制求值顺序。
两个相邻的操作符先执行哪个?取决于他们的优先级。如果两者的优先级相同,取决于他们的结合性。

#include<stdio.h>
//首先确定优先级,相邻操作符按照优先级高低计算
//优先级相同的情况下,结合性才起作用
//
int main() {
	int a = 1;
	int b = 2;
	int c = 4;
	
	int d = a * 4 + b / 3 + c;//相邻操作符才讨论优先级

	int e = a + b + c;
	printf("%d\n", d);
	
	return 0;
}

优先级:

在这里插入图片描述

2.一些问题表达式

(1)典例1

在这里插入图片描述
在计算的时候,由于星号比+的优先级高,只能保证,星号的计算是比+早,但是优先级并不能决定第三个*比第一个+早执行。
在这里插入图片描述
运算顺序不一样,很可能导致运算结果不一样。

(2)典例2

在这里插入图片描述
操作符的优先级只能决定自减–的运算在+的运算的前面,但是我们并没有办法得知,+操作符的左操作数的获取在右操作数之前还是之后求值,所以结果是不可预测的,是有歧义的。

(3)典例3

在这里插入图片描述
在不同的编译器上计算结果是不同的。

(4)典例4

在这里插入图片描述
虽然在大多数的编译器上求得结果都是相同的。但是上述代码answer = fun() - fun() * fun(); 中我们只能通过操作符的优先级得知:先算乘法,再算减法。
函数的调用先后顺序无法通过操作符的优先级确定。


总结

操作符这块的知识较为冗杂,但是只要你认真细心地去做,去思考,就能体会到很多不同的知识,这篇博客除了讲解了操作符,还跟大家讲解了在计算机内部的存储方式以及二进制的原码、补码和反码的知识,相信大家在看完以后会有很多不错的收获!!!


客官,码字不易,给个三连支持一下吧!!!

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

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

相关文章

《码出高效:java开发手册》六-数据结构与集合(二)

前言 接上篇&#xff0c;第六章第二部分&#xff0c;上篇讲到了红黑树的FixAfterInsertion方法&#xff0c;这个方法原理与fixAfterDelete类似&#xff0c;只讲这个添加时的调整方法 代码可以看到&#xff0c;调整后的根节点一定是黑色的&#xff0c;叶子节点可红可黑&#x…

Spring 之 @Import 注解使用与源码浅析

1、Import 的作用&#xff1f; 再说 Import 之前先回忆下 Component 的作用&#xff0c;在类上标注该注解&#xff0c;该类就能够被 Spring 扫描封装成 BeanDefinition 并注册到容器中。但现在需要将第三方 jar 包、或者其他路径下面的包中的类也要被扫描注册呢&#xff1f;使…

Unity 制作一个简单的星系

使用素材&#xff1a; 1.Planets with Space Background in Flat Style 2.Planet Icons 创建场景 编写脚本 using System.Collections; using System.Collections.Generic; using UnityEngine;public class Cytaster : MonoBehaviour {[SerializeField]private float rotate_s…

【LeetCode】矩阵置零 [M](矩阵)

73. 矩阵置零 - 力扣&#xff08;LeetCode&#xff09; 一、题目 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,1,1],[1,0,1],[1,1,1]] 输出&a…

uni-app - 封装全局 API 调用弹框组件

uni-app - 在纯 JS 文件中调用自定义弹框组件 / 封装全局 API 调用弹框组件&#xff08;解决小程序、APP 无法使用 document.body.appendChild 插入组件节点&#xff09;适配全端 uni-app中实现一个全局弹层组件 引用超级全局组件方案 一、安装 npm install vue-inset-loade…

零入门容器云网络-9:命令行式操作tun设备介绍

已发表的技术专栏&#xff08;订阅即可观看所有专栏&#xff09; 0  grpc-go、protobuf、multus-cni 技术专栏 总入口 1  grpc-go 源码剖析与实战  文章目录 2  Protobuf介绍与实战 图文专栏  文章目录 3  multus-cni   文章目录(k8s多网络实现方案) 4  gr…

测开工具:spring boot 实现同步数据库表结构

源码&#xff1a; GitHub - 18713341733/mysqlsync 一、使用场景 一个项目&#xff0c;有多套开发环境。有一套标准的数据库&#xff0c;不同的开发环境&#xff0c;有各自的一套数据库。 标准数据库的表结构经常发生变化&#xff0c;不同的开发环境中的数据库&#xff0c;…

C#,图像二值化(04)——全局阈值 Kittler 算法及其源程序

1、Kittler算法&#xff08;最小误差法&#xff09;概述 最小误差法是 J. Kittler & J. Illingworth 1986年在《MINIMUM ERROR THRESHOLDING》文章中提出的一种基于直方图的阈值分割方法,简称 Kittler 算法。其思想:假设灰度图像由目标和背景组成,且目标和背景满足一混合高…

11个技巧让你成为更好的 Typescript 程序员

学习 Typescript 通常是一次重新发现之旅。您的最初印象可能非常具有欺骗性&#xff1a;这不就是一种注释 Javascript 的方式&#xff0c;所以编译器可以帮助我找到潜在的错误吗&#xff1f; 通过 r/mevlixreddit 虽然这句话通常是正确的&#xff0c;但随着您继续前进&#xff…

【聆思CSK6 视觉AI开发套件试用】AI识别试用以及闭坑方案

本篇文章来自极术社区与聆思科技组织的CSK6 视觉AI开发套件活动&#xff0c;更多开发板试用活动请关注极术社区网站。作者&#xff1a;X Y Z 非常感谢能有这次机会体验聆思CSK6 视觉AI开发套件。上班的一大早收到了快递&#xff0c;迫不及待的打开快递。必须先来个图&#xff0…

4个技巧,节约网络工程师一半的时间

01 批量ping网段 对于一个网段ip地址众多&#xff0c;如果单个检测实在麻烦&#xff0c;那么你就可以直接批量ping网段检测&#xff0c;那个ip地址出了问题&#xff0c;一目了然。 先看代码&#xff0c;直接在命令行窗口输入&#xff1a; for /L %D in (1,1,255) do ping 10…

渗透测试神器--Burp Suite

一、介绍 Burp Suite 是用于攻击web 应用程序的集成平台。Burp Suite是一款信息安全从业人员必备的集成型的渗透测试工具&#xff0c;它采用自动测试和半自动测试的方式&#xff0c;包含了Proxy、Spider、Scanner、Intruder、Repeater、Sequencer、Decoder、Comparer等工具模块…

uniapp 窗口小工具、桌面小部件、微件 Ba-AppWidget

简介&#xff08;下载地址&#xff09; Ba-AppWidget 是一款窗口小工具&#xff08;桌面小部件、微件&#xff09;插件&#xff0c;默认为音乐播放器的样式&#xff0c;有其他界面需要&#xff0c;可联系作者定制。 支持点击事件监听支持动态更改页面内容支持设置小工具的预览…

区块链(一): 以太坊基础知识

目录什么是区块链&#xff1f;什么是以太坊&#xff1f;什么是加密货币&#xff1f;以太坊与比特币有什么不同&#xff1f;以太坊能做什么&#xff1f;什么是智能合约&#xff1f;以太坊社区以太坊白皮书什么是区块链&#xff1f; 区块链是一个交易数据库&#xff0c;在网络中…

容器,容器技术,云容器相关入门知识

前言 最近面试了一家国企&#xff0c;交谈愉快&#xff0c;对方的工程师问到容器时&#xff0c;突然愣了一下。脑子里有学习前端时候学习的docker&#xff0c;但印象里docker可不能代表容器技术&#xff0c;于是学习容器相关知识后整理相关知识以作巩固。 什么是容器 有点开…

SuperMap iDesktop/iDesktopX 端性能优化

作者&#xff1a;yd&hyy 一、背景 在使用iDesktop/iDesktopX的三维场景加载GIS数据的过程中&#xff0c;随着数据的种类、大小、数量的增多&#xff0c;往往会有很多的性能问题&#xff0c;加载速率缓慢&#xff0c;数据显示清晰度不足&#xff0c;多数据交叠显示错误&am…

『分分钟玩转VueRouter●上』VueRouter的一些基础配置

文章目录前言一、vue中如何使用VueRouter?二、路由使用的基本配置1.多级路由配置2.路由中的query参数3.命名路由4.路由的params参数5.路由的props配置6.router-link的replace属性7.通配符路由前言 计算机网络中有一个路由的概念&#xff1a;路由是指网络数据包发送到目的地址的…

php宝塔搭建部署实战SDCMS蓝色通用宽屏企业网站源码

大家好啊&#xff0c;我是测评君&#xff0c;欢迎来到web测评。 本期给大家带来一套php开发的SDCMS蓝色通用宽屏企业网站源码&#xff0c;感兴趣的朋友可以自行下载学习。 技术架构 PHP7.2 nginx mysql5.7 JS CSS HTMLcnetos7以上 宝塔面板 文字搭建教程 下载源码&…

maven 继承和聚合的区别

maven 继承和聚合的区别 参考 https://cloud.tencent.com/developer/article/1397748 继承 目的&#xff1a;统一管理version版本&#xff0c;少写冗余代码。使用&#xff1a; 父类pom不写业务&#xff0c;只写 pom的jar包版本等信息&#xff0c;子类中使用 parent 标签&…

STM32G473CBT6关于ADC采集的总结

STM32G473CBT6单片机在浮点运算&#xff0c;信号采集、数据处理方面有很大的用途。因相关的资料较少&#xff0c;特此做一下笔记&#xff0c;方便后期使用。STM32CubeMX软件比较强大&#xff0c;兼容IAR和keil方便直接生成代码文件&#xff0c;但相关的库不熟悉&#xff0c;好东…