首页 > 其他分享 >操作符的补充&详解

操作符的补充&详解

时间:2022-11-02 22:02:28浏览次数:51  
标签:return 补充 int 详解 操作符 printf -- main

算数操作符

1.除了%操作符之外,其他的几个操作符可以作用于整数和浮点数。 2.对于/操作符,如果两个操作数都为整数,执行整数除法,而只要有浮点数执行的就是浮点数除法 3.%操作符的两个操作数必须为整数,返回的是整除之后的余数

移位操作符(只能作用于整数)

右移动(>>)

1.算术右移(常见)

右边丢弃,左边补原符号位

2.逻辑右移

右边直接丢弃,左边补0

警告:对于移位操作符,不要移动负数位,这是一种未定义操作符

//int main() {
// int a = 16;
// //>> -- 右移操作符
// //移动的是二进制位
// // 00000000000000000000000000000000
// //16 -- 10000
// // 00000000000000000000000000010000 -- 16
// // 00000000000000000000000000001000 -- 8
//
// int b = a >> 1;
// printf("%d\n", b);//8
// return 0;
//
//}

//int main() {
// //二进制中首位的1表示负号
// int a = -1;
// //整数的二进制表示有:原码,反码,补码
// //储存到内存的是补码
// //10000000000000000000000000000001 - 原码(-1)
// //11111111111111111111111111111110 - 反码
// //11111111111111111111111111111111 - 补码
// return 0;
//}

左移操作符

左边丢弃,右边补齐

int main() {
int a = 5;//00000000000000000000000000000101 -- 5
//左移操作符
int b = a << 1;//00000000000000000000000000001010 -- 10
return 0;
}
位操作符(操作数必须是整数)

& -- 按位与

| -- 按位或

^ -- 按位异或

int main() {
//& - 按2进制位与
//int a = 3;
//int b = 5;
//int c = a & b;//1
//00000000000000000000000000000011
//00000000000000000000000000000101
//00000000000000000000000000000001 -- 按位与
//printf("%d\n", c); 1
// | -- 按二进制位或
//int a = 3;
//int b = 5;
//int c = a | b;
////00000000000000000000000000000011
////00000000000000000000000000000101
////00000000000000000000000000000111
//printf("%d\n", c);//7
// ^ -- 按二进制位异或
//相同为0,相异为1
int a = 3;
int b = 5;
int c = a ^ b;
//00000000000000000000000000000011
//00000000000000000000000000000101
//00000000000000000000000000000110
printf("%d\n", c);//6
return 0;
}
两个变量交换
int main() {
int a = 3;
int b = 6;
//int tmp = 0;//创建临时变量的方法
printf("before: a=%d b=%d\n", a, b);
//tmp = a;
//a = b;
//b = tmp;
//加减法交换 - 可能会溢出
//a = a + b;//a = 8 b = 6
//b = a - b;//a = 8 b = 3
//a = a - b;//a = 6 b = 3

//异或的方法
//a - 011 b - 110
a = a ^ b;//a -- 101
b = a ^ b;//b -- 011 = 3
a = a ^ b;//a -- 110 = 6
printf("after:a=%d b=%d\n", a, b);
return 0;
}
求二进制里面1的个数
int main() {
int num = 0;
int count = 0;//计数器
scanf("%d", &num);
int i = 0;
for (i = 0; i < 32; i++) {

if (1 == ((num >> i) & 1))
//每循环一次如果符合条件则计数一次
count++;
}
printf("%d\n", count);
}
赋值操作符

变量创建的时候给值叫初始化

变量创建过了之后给值叫赋值

复合赋值

单目操作符

举个别例子

int main() {
int a = 0;
if (!a) { //a为假打印
printf("呵呵!\n");
}
return 0;
}

&(取地址操作符)
*(解引用操作符)

int main() {
int a = 0;
int* p=&a;//取地址操作符
*p;//解引用操作符 -- 通过*p找到a
return 0;
}

sizeof

sizeof()里的表达式不参与运算

int main() {
int a = 10;
char c = 'r';
char* p = &c;
int arr[10] = { 0 };
//sizeof 计算的变量所占内存空间的大小,单位是字节
printf("%d\n", sizeof(a));//4 -- 通过变量名
printf("%d\n", sizeof(int));//4 -- 通过类型访问

printf("%d\n", sizeof(c));//1
printf("%d\n", sizeof(char));//1

printf("%d\n", sizeof(p));//8
printf("%d\n", sizeof(char*));//8

printf("%d\n", sizeof(arr));//40
printf("%d\n", sizeof(int [10]));//40

return 0;
}

~(按位取反)

int main() {
int a = 11;
a = a | (1 << 2);
printf("%d\n", a);//15
//00000000000000000000000000001011
//00000000000000000000000000000100
//1<<2
//00000000000000000000000000000001
//a - 00000000000000000000000000001111

a = a& (~(1 << 2));
printf("%d\n", a);//11
//1<<2 - 00000000000000000000000000000100
//~(1 << 2) - 11111111111111111111111111111011
//a - 00000000000000000000000000001111
//a& (~(1 << 2)) - 00000000000000000000000000001011

//int a = 0;
////~ 按(2进制)位取反
////00000000000000000000000000000000
////11111111111111111111111111111111 - 补码
////11111111111111111111111111111110 - 反码
////10000000000000000000000000000001 - 原码
//printf("%d\n", ~a);
return 0;
}

前置++,后置++

int main() {
int a = 10;
//printf("%d\n", ++a);//前置++,先++后使用 - 11
printf("%d\n", a++);//后置++,先使用后++ - 10

return 0;
}

强制类型转换

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

隐式类型转换

整型提升

C的整形运算总是至少以缺省整型类型的精度来进行运算的。

为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整形,这种转换称为整型提升

整形提升的意义

表达式的整形运算要在CPU的相应运算器件内执行,CPU内整形运算器(ALU)的操作数的字节长度一般就是int的字节长度,同时也是CPU的通用寄存器的长度。

因此,即使两个char类型的相加,在CPU执行时实际上也先要转换为CPU内整形操作数的标准长度。 通用CPU是难以直接实现两个8比特字节直接相加运算,所以,表达式中各种长度可能小于int长度的整型值,都必须先转换为int或unsigned int,然后才能送入CPU去执行运算

//int main() {
// char a = 3;
// //00000000000000000000000000000011
// //00000011 - a
// char b = 127;
// //00000000000000000000000001111111
// //01111111 - b
//
// //a和b如何相加
// //00000000000000000000000000000011
// //00000000000000000000000001111111
// //00000000000000000000000010000010
//
// char c = a + b;
// //c=10000010
// //11111111111111111111111110000010 - 补码
// //11111111111111111111111110000001 - 反码
// //10000000000000000000000001111110 - 原码
// //-126
// printf("%d\n", c);// -126
// return 0;
//}

如何进行整型提升

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

//int main() {
// char a = 3;
// //00000000000000000000000000000011
// //00000011 - a
// char b = 127;
// //00000000000000000000000001111111
// //01111111 - b
//
// //a和b如何相加
// //00000000000000000000000000000011
// //00000000000000000000000001111111
// //00000000000000000000000010000010
//
// char c = a + b;
// //c=10000010
// //11111111111111111111111110000010 - 补码
// //11111111111111111111111110000001 - 反码
// //10000000000000000000000001111110 - 原码
// //-126
// printf("%d\n", c);// -126
// return 0;
//}
//例题
int main() {
char a = 0xb6;
short b = 0xb600;
int c = 0xb6000000;
if (a == 0xb6)
printf("a");
if (b == 0xb600)
printf("b");
if (c == 0xb6000000)
printf("c");
return 0;
}
//例题2
int main() {
char c = 1;
printf("%u\n", sizeof(c));//1
//c只要参与表达式运算,就是发生整型提升,表达式+c,就会发生提升,所以sizeof(+c)是4个字节
//表达式-c也会发生整型提升,sizeof(-c)是4个字节,但是sizeof(c)就是1个字节
printf("%u\n", sizeof(+c));//4
printf("%u\n", sizeof(!c));//1
return 0;
}
算数转换

long double

double

float

unsigned long int

long int

unsigned int

int

算术转换要合理,不然会有一些潜在问题

操作符的属性

复杂表达式的求值有三个影响因素。

1.操作符的优先级

2.操作符的结合性

3.是否控制求值顺序

两个相邻的操作符先执行哪个?取决于它们的优先级,如果是相同操作符,则看他们的结合性

//int main() {
// int a = 10;
// int b = 20;
// int c = b + a + 3;
// return 0;
//
//}

一些问题表达式

表达式1
a*b+c*d+e*f//问题表达式
计算机的运算顺序
a*b
c*d
a*b+c*d
e*f
a*b+c*d+e*f
或者:
a*b
c*d
e*f
a*b+c*d+e*f
//假如将数换成表达式,可能会出现错误

表达式2
c + --c;
注释:同上,操作符的优先级只能决定自减的运算在+的运算的前面,但是我们并没有办法得知,+操作符的左操作数的获取在右操作数之前还是之后求值,所以结果不可预测的,是有歧义的。


表达式3
int main(){
int i=10;
i = i-- - --i*(i=-3) * i++ + ++i
printf("i=%d\n",i)
return 0;
}

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

表达式5
int main() {
int i = 1;
int a = (++i) + (++i) + (++i);
printf("a= %d\n", a);
return 0;
}
Linux用gcc下结果是10
win用VS下结果是12

所以不要写华而不实的代码,要写有唯一计算路径的代码

表达式3在不同的编译器中测试结果:非法表达式程序的结果

操作符的补充&详解_操作符

操作符的补充&详解_操作数_02

 这个操作符优先级图我是在网上找的,也有不同的但是都差不多。




标签:return,补充,int,详解,操作符,printf,--,main
From: https://blog.51cto.com/u_15812262/5818391

相关文章

  • 类的作用域详解(C++ primer7.4笔记)
    7.4类的作用域名字查找的过程:(查找匹配的声明)在名字所在块中寻找语句,查找使用名字之前出现的声明。如果没找到,查找外层作用域还没找到就报错类的定义分为两步处理:......
  • BigDecimal保留两位小数点示例详解
     BigDecimal保留两位小数点非常简单,BigDecimal是一个java数据类型,它能有效的保持数据的精度,下面是一个BigDecimal保留两位小数点的用法示例。publicclassMyDemo{pu......
  • C语言 操作符
    #include<stdio.h>//操作符//intmain()//{////double去模操作符两边必须是整数类型操作符////移位操作符<<--左移操作符>>--右移操作符移动的是二进制位!!!!!......
  • JavaWeb三大组件之Filter学习详解
    JavaWeb三大组件之Filter学习详解Filter基本上可以说存在所有的JavaWeb项目中,比如最基本的一个请求参数的编码​​CharacterEncodingFilter​​,大家一般都会配置下,那么filte......
  • python 魔术方法__str__及__repr__方法详解
    __str__方法__repr____str__自定义类的时候__str__方法的作用。这个魔术方法__str__主要的作用是在print(实例对象)的时候返回你指定的字符串,一般来说在定义类的时候不......
  • hive的trunc函数详解
    一、日期TRUNC函数为指定元素而截去的日期值。其具体的语法格式:TRUNC(date[,fmt])其中:date一个日期值fmt日期格式,该日期将由指定的元素格式所截去。忽略它则由最......
  • G1 垃圾收集器深入剖析(图文超详解)
    G1(GarbageFirst)垃圾收集器是目前垃圾回收技术最前沿的成果之一。G1同CMS垃圾回收器一样,关注最小时延的垃圾回收器,适合大尺寸堆内存的垃圾收集。但是,G1最大的特点是......
  • Node_exporter+Prometheus+Grafana 安装配置详解
    在进行性能测试时,想直观看到服务器的CPU、内存占用多少,可以搭建prometheus+node_exporter+grafana来实现。通过node_exporter把从服务器(即被监控机器)采集到的信息发到pr......
  • 架构(domain层详解...)
    架构 理解:1、Repo数据源,Domain把数据源数据转换为界面使用的数据  domain层详解domain的概念,通常会分很多层,比如经典的三层架构,控制层、业务层、数据访问层(DA......
  • 工业交换机端口故障问题详解
    工业交换机故障一般可以分为硬件故障和软件故障两大类。硬件故障主要指交换机电源、背板、模块、端口等部件的故障,接下来小编来给大家介绍下工业交换机端口故障的问题,一起来......