今天我们大家一起来学习操作符
文章目录
1.二进制和进制转换
1.1 2进制转10进制
2进制1101转化为十进制
1.3 10进制转2进制数字
1.4 2进制转8进制
8进制的数字每⼀位是0到7的数字,各自写成2进制,
最多有3个2进制位就足够了,比如7的二进制是111,
所以在2进制转8进制数的时候,
从2进制序列中右边低位开始向左每3个2进制位会换算⼀个8进制位,
剩余不够3个2进制位的直接换算。
如:
2进制的 01101011,换成8进制:0153,
0开头的数字,会被当做8进制。
1.5 2进制转16进制
16进制的数字每⼀位是0到9, a到f的数字,
各自写成2进制,最多有4个2进制位就足够了,
比如 f 的⼆进制是1111,所以在2进制转16进制数的时候,
从2进制序列中右边低位开始向左每4个2进制位会换算⼀个16进制位,
剩余不够4个⼆进制位的直接换算。
如:
2进制的01101011,换成16进制:0x6b,
16进制表示的时候前面加0x
2.原码、反码、补码
整数的2进制表示方法有三种,即原码、反码和补码
有符号整数的三种表示方法均有符号位和数值位两部分,
2进制序列中,最高位的1位是被当做符号位,剩余的都是数值位。
符号位都是用0表示“正”,用1表示“负”。
正整数的原、反、补码都相同。
负整数的三种表示方法各不相同。
原码:直接将数值按照正负数的形式翻译成⼆进制得到的就是原码。
反码:将原码的符号位不变,其他位依次按位取反就可以得到反码。
补码:反码+1就得到补码。
补码得到原码也是可以使用:取反,+1的操作。
3.移位操作符
3.1左移操作符
移位规则:左边抛弃、右边补0
3.2右移操作符
3.2.1逻辑右移:左边用0填充,右边丢弃
3.2.2 算术右移:左边用原该值的符号位填充,右边丢弃
4.位操作符:&、|、^、~
他们的操作数必须是整数。
4.1按位与&
按位与操作符(&)是C语言中的一种位操作符,
用于对两个整数的二进制表示进行逐位与运算。
具体来说,它会将两个操作数的每一个二进制位进行比较,
只有当两个操作数的对应位都为1时,结果的对应位才为1,否则为0。
4.2按位或|
按位或操作符(|)是C语言中的一种位操作符,
它用于对两个整数的二进制表示进行逐位或运算。
具体来说,它将两个操作数的每一位进行比较,
只要两个操作数的对应位中有一个是1,结果的对应位就为1;
只有当两个操作数的对应位都是0时,结果的对应位才为0。
4.3按位异或^
按位异或操作符(^)是C语言中的一种位操作符,
它用于对两个整数的二进制表示进行逐位异或运算。
异或运算的特点是:当两个对应的二进制位相同时,结果为0;
当两个对应的二进制位不同时,结果为1。
4.4按位取反
按位取反,也称为位运算中的**“NOT”操作或按位否定**,
是一种二进制数的算术操作,
它将每个二进制位的值从0变为1,从1变为0。
例如,
在计算机科学中,
如果一个整数的二进制表示为1010,
对其进行按位取反后会变成0101。
这种操作常用于数据处理、位图操作、加密算法等领域,
可以高效地改变数字的某些特定位状态。
在编程语言中,大多数都有专门的位运算符来进行这个操作,
比如在C++中就是~操作符。
5.逗号表达式
1 exp1, exp2, exp3, …expN
逗号表达式,就是用于隔开多个表达式。
逗号表达式,从左向右依次执行。
整个表达式的结果是最后一个表达式的结果。
6. 结构成员访问操作符
结构体这种自定义的数据类型,让程序员可以自己创造适合的类型。
6.1结构体的声明
描述⼀个学⽣:
struct Stu
{
char name[20];//名字
int age;//年龄
char sex[5];//性别
char id[20];//学号
}; //**分号不能丢**
6.2结构体变量的定义和初始化
//代码1:变量的定义
struct Point
{
int x;
int y;
}p1;
//声明类型的同时定义变量p1
struct Stu //类型声明
{
char name[15];//名字
int age;
//年龄
};
struct Stu s1 = {"zhangsan", 20};//初始化
6.3结构体访问成员
6.3.1直接访问
结构体成员的直接访问是通过点操作符(.)访问的。
点操作符接受两个操作数。
#include <stdio.h>
struct Point
{
int x;
int y;
}p = {1,2};
int main()
{
printf("x: %d y: %d\n", p.x, p.y);
return 0;
}
使用方式:结构体变量.成员名
6.3.2间接访问
#include <stdio.h>
struct Point
{
int x;
int y;
};
int main()
{
struct Point p = {3, 4};
struct Point *ptr = &p;
ptr->x = 10;
ptr->y = 20;
printf("x = %d y = %d\n", ptr->x, ptr->y);
return 0;
}
使用方式:结构体指针->成员名
7.下标访问[]、函数调用()
接受一个或者多个操作数:
第一个操作数是函数名,剩余的操作数就是传递给函数的参数。
7.1 [ ]
操作数:⼀个数组名 + ⼀个索引值(下标)
7.2()
8.操作符的属性:优先级、结合性
8.1优先级
优先级指的是,如果⼀个表达式包含多个运算符,
哪个运算符应该优先执行。各种运算符的优先级是不⼀样的。
8.2结合性
如果两个运算符优先级相同,优先级没办法确定先计算哪个了,
这时候就看结合性了,
则根据运算符是左结合,还是右结合,决定执行顺序。
大部分运算符是左结合(从左到右执行),
少数运算符是右结合(从右到左执行),比如赋值运算符( = )。
以下7个较重要:
- 圆括号( () )
- 自增运算符( ++ ),自减运算符( – )
- 单目运算符( + 和 - )
- 乘法( * ),除法( / )
- 加法( + ),减法( - )
- 关系运算符( < 、 > 等)
- 赋值运算符( = )
由于圆括号的优先级最高,可以使用它改变其他运算符的优先级。
9.表达式求值
9.1整型提升
//负数的整形提升
char c1 = -1;
//变量c1的⼆进制位(补码)中只有8个⽐特位:
//1111111
//因为 char 为有符号的 char
//所以整形提升的时候,⾼位补充符号位,即为1
//提升之后的结果是:
//11111111111111111111111111111111
//正数的整形提升
char c2 = 1;
//变量c2的⼆进制位(补码)中只有8个⽐特位:
//00000001
//因为 char 为有符号的 char
//所以整形提升的时候,⾼位补充符号位,即为0
//提升之后的结果是:
//00000000000000000000000000000001
9.2算术转换
如果某个操作符的各个操作数属于不同的类型,
那么除非其中⼀个操作数的转换为另⼀个操作数的类型,
否则操作就无法进行。下面的层次体系称为寻常算术转换。
long double
double
float
unsigned long int
long int
unsigned int
int
如果某个操作数的类型在上面这个列表中排名靠后,
那么⾸先要转换为另外⼀个操作数的类型后执行运算。
即使有了操作符的优先级和结合性,
我们写出的表达式依然有可能不能通过操作符的属性确定唯一的计算路径,那这个表达式就是存在潜在风险的,
建议不要写出特别复杂的表达式。
练习
1.不能创建临时变量(第三个变量),实现两个整数的交换。
代码
#include<stdio.h>
int main()
{
int a;
int b;
printf("请输入要交换的两个数\n");
scanf("%d %d", &a, &b);
a = a ^ b;
b = a ^ b;
a = a ^ b;
printf("a = %d b = %d", a, b);
return 0;
}
运行结果
2.编写代码实现:求一个整数存储在内存中的二进制中1的个数。
代码
#include<stdio.h>
int Calculate(int x)
{
int count = 0;
while (x)
{
count++;
x = x & (x - 1);
}
return count;
}
int main()
{
int ret = 0;
printf("请输入要计算的数字\n");
int x;
scanf("%d", &x);
ret = Calculate(x);
printf("数字中二进制中的1的个数为%d\n", ret);
return 0;
}
运行结果
3.二进制位置0或者置1
代码
#include<stdio.h>
int main()
{
int a = 13;
//0000000000000000000001101
//0000000000000000000011101 将第五位置1
//0000000000000000000001101 再将第五位置0
a = a | (1 << 4);
printf("打印第五位置1后的值:%d\n",a);//29
a = a & ~(1 << 4);
printf("打印置为0的值:%d\n",a);
return 0;
}
运行结果
4.单身狗1
在一个整型数组中,只有一个数字出现一次,
其他数组都是成对出现的,请找出那个只出现一次的数字。
例如:
数组中有:1 2 3 4 5 1 2 3 4,只有5出现一次,
其他数字都出现2次,找出5
代码
#include<stdio.h>
int Find_single_dog(int arr[], int sz)
{
int ret = 0;
int i;
for ( i = 0; i < sz; i++)
{
ret ^= arr[i];
}
return ret;
}
int main()
{
int arr[9] = { 1,2,3,4,5,1,2,3,4 };
int sz = sizeof(arr) /sizeof(arr[0]);
int ret = Find_single_dog(arr,sz);
printf("只出现一次的数字是%d\n", ret);
return 0;
}
运行图片
5.打印整数二进制的奇数位和偶数位
获取一个整数二进制序列中所有的偶数位和奇数位,
分别打印出二进制序列
代码
#include<stdio.h>
void Printbit(n)
{
int i = 0;
int j = 0;
for (i = 31; i >= 1; i-=2)
{
printf("%d ", (n >> i) & 1);
}
printf("\n");
for (i = 30; i >= 0; i -= 2)
{
printf("%d ",(n >> i) & 1);
}
printf("\n");
}
int main()
{
printf("请输入一个整数:\n");
int n;
scanf("%d", &n);
Printbit(n);
return 0;
}
运行结果
6.求两个数二进制中不同位的个数
编程实现:
两个int(32位)整数m和n的二进制表达中,
有多少个位(bit)不同?
输入例子:
1999 2299
输出例子:7
代码
#include<stdio.h>
int main()
{
int a, b;
printf("请输入两个整数:\n");
scanf("%d %d", &a, &b);
int count = 0;
int n = 32;
int tmp;
tmp = a ^ b;
while (tmp)
{
tmp = tmp & (tmp - 1);
count++;
}
int ret = count;
printf("有%d位不同\n",ret);
return 0;
}
运行结果
总结
对操作符我们要知道每个操作符的用法,注意优先级和结合性,大家一定要巩固好基础,多练习
对操作符的分享就到这里了,如果感觉不错,希望可以给博主点个赞或者关注,感谢大家的支持,成为我继续分享的动力,还有什么问题和建议可以在评论区评论,拜拜。