C语言操作符详解(上)

提示:本篇内容的学习目标是学会各种操作符的使用,以及操作符如何影响表达式求值的
C语言操作符详解(上)_第1张图片

文章目录

  • 前言
  • 一、算术操作符 + - * / %(运算符)
  • 二、移位操作符(操作数只能是整数)
  • 三、位操作符(操作数必须是整数)
  • 四、赋值操作符
    • =
    • 复合操作符
  • 六、单目操作符
  • 七、关系操作符
  • 八、逻辑操作符


前言

一、算术操作符 + - * / %(运算符)

除法注意点: / 除法 得到的是商
1.除法操作符的两个操作数都是整数的话,执行的是整数除法.用%d打印
2.除法操作符的两个操作数只要有一个浮点点数,执行的是小数除法.用%lf打印
% 取模(取余) 得到的是余数:
1.取模操作符的两个操作数必须是整数,返回的是整除之后的余数.
2.除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数

#define _CRT_SECURE_NO_WARNINGS 1
#include
int main() {
	//printf("%lf\n", 10 / 3);   //不能这么写,因为两个操作数都是整数,应该用%d
	printf("%lf\n", 10 / 3.0);
	printf("%d\n", 10 / 3);
}

C语言操作符详解(上)_第2张图片

二、移位操作符(操作数只能是整数)

C语言操作符详解(上)_第3张图片
移位操作符移动的是二进制的位
左移操作符: 左边丢弃,右边补0

数值的表示形式:
2进制,8进制,10进制,16进制
10进制的数据中,都是0-9的数字组成的
2进制的数据中,0-1的数字组成的
8进制的数据中,0-7的数字组成的
16进制的每一位是:
0~15
0 1 2 3 4 5 6 7 8 9 a b c d e f

比如:
表示数值10
1010----2进制
12-------8进制
10-------10进制
a---------16进制

数据的二进制表示:
整数的二进制表示形式有三种: 原码反,码,补码
原码:
把一个数按照正负直接翻译成二进制就是原码
最高位表示符号位,0表示正数,1表示负数
正整数的原码反码补码相同,
负整数的原码反码补码是要计算的
反码:
原码的符号位不变,其他位按位取反就是反码
补码:
反码+1

举例说明:
5,-5是整数,整数是存放在整型变量中的
一个整型变量是4个字节~32比特位

5:
原码 00000000000000000000000000000101
反码 00000000000000000000000000000101
补码 00000000000000000000000000000101
-5:
原码10000000000000000000000000000101
反码 11111111 11111111 11111111 11111010
补码 11111111 11111111 11111111 11111011

整数在内存中存储的是:二进制补码
4个比特位可以作为一个16进制数
例如:-5
补码 11111111 11111111 11111111 11111011
4个一组表示成16进制:
FF FF FF FB

正整数左移操作符举例说明:
3的二进制位:
00000000 00000000 00000000 00000011
向左移动一位,左边丢弃,右边补0
C语言操作符详解(上)_第4张图片

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main() {
	int a = 3;
	//3的二进制位:(正数的原码反码补码相同)
	//00000000 00000000 00000000 00000011
	
	int b=a << 1;
	//向左移动一位,左边丢弃,右边补0
	//b是正数,原码反码补码相同
	//00000000 00000000 00000000 00000110  
	//b也就是6
	printf("%d\n", b);
	printf("%d\n", a);

	return 0;
}

C语言操作符详解(上)_第5张图片
负整数左移操作符举例说明:
原码------>补码:取反+1
补码------>原码:-1,取反 或者 取反+1

-3的二进制位左移一位:
由于整数在内存中存储的是补码,左移的时候实际上是将补码左移一位,右边补0.
首先求出-3的补码,左移补0之后得到的是结果的补码,还需要转换成原码,最后通过原码得出结果是多少
C语言操作符详解(上)_第6张图片

 int main() {
	int a =-3;
	/*-3的二进制位:
	10000000 00000000 00000000 00000011   -3的原码
	11111111 11111111 11111111 11111100   -3的反码
	11111111 11111111 11111111 11111101   -3的补码*/
	// 
	
	int b=a << 1;
	//-3的补码向左移动一位,左边丢弃,右边补0得到结果的补码
	//11111111 11111111 11111111 11111010   b的补码      
	//11111111 11111111 11111111 11111001   b的反码
	//10000000 00000000 00000000 00000110   b的原码 -6

	printf("%d\n", b);
	printf("%d\n", a);

	return 0;
}

C语言操作符详解(上)_第7张图片
右移操作符:
1.>> 算术右移:
右边丢弃,左边用原来的符号来填充
2.>> 逻辑右移:
右边丢弃,左边直接用0来填充

右移的时候,到底采用的是算术右移还是逻辑右移,是取决于编译器的!!
由下面的代码可以看出,vs2019编译器采用的是算术右移.

int main() {
	int a = -5;
	int b = a >> 1;
	//10000000 00000000 00000000 00000101
	//11111111 11111111 11111111 11111010
	//11111111 11111111 11111111 11111011
	printf("b=%d\n", b);
	//算术右移
	//11111111 11111111 11111111 11111101
	//10000000 00000000 00000000 00000010
	//10000000 00000000 00000000 00000011     -3
	printf("a=%d\n", a);

	return 0;
}

C语言操作符详解(上)_第8张图片

三、位操作符(操作数必须是整数)

位:指的是二进制位
C语言操作符详解(上)_第9张图片

int main() {
	int a = 3;
	int b = -5;
	int c = a & b;
	//00000000 00000000 00000000 00000011  3的补码
	//10000000 00000000 00000000 00000101  -5的原码
	//11111111 11111111 11111111 11111010  -5的反码
	//11111111 11111111 11111111 11111011  -5的补码

	//00000000 00000000 00000000 00000011  3的补码
	//11111111 11111111 11111111 11111011  -5的补码
	//00000000 00000000 00000000 00000011   a&b的补码,由于是正整数,原码也是这个
	printf("%d\n", c);  //3

	int d = a | b;  //按位或
	//00000000 00000000 00000000 00000011  3的补码
	//11111111 11111111 11111111 11111011  -5的补码
	//11111111 11111111 11111111 11111011  a|b的补码,可以发现与-5的补码一样,所以他的原码数值等于-5
	printf("%d\n", d);

	int e = a ^ b;  //按位异或--对应的二进制位相同为0,相异为1
	//00000000 00000000 00000000 00000011  3的补码
	//11111111 11111111 11111111 11111011  -5的补码
	//11111111 11111111 11111111 11111000  a^b的补码
	//11111111 11111111 11111111 11110111  补码-1
	//00000000 00000000 00000000 00001000  取反得到原码,结果为-8

	printf("%d\n", e);

}

C语言操作符详解(上)_第10张图片

交换a和b的值:
方法一:创建临时变量

int main() {
	int a = 3;
	int b = 5;
	printf("交换前:a=%d b=%d\n", a, b);
	int tmp = 0;
	tmp = 0;
	tmp = a;
	a = b;
	b = tmp;
	printf("交换后:a=%d b=%d\n", a, b);
}

C语言操作符详解(上)_第11张图片
方法二:不创建临时变量
存在潜在风险,当数字过大时,加和之后可能超出整数的最大范围,有一定局限性

int main() {
	int a = 3;
	int b = 5;
	printf("交换前:a=%d b=%d\n", a, b);
	a = a + b;
	b = a - b;
	a = a - b;
	printf("交换后:a=%d b=%d\n", a, b);

	return 0;
}

C语言操作符详解(上)_第12张图片
方法三:使用异或操作符,不创建临时变量
注意两个公式:
a^a=0
0^a=a

3^ 3^5=5
011 3
011 3
000 3^3
101 5
101 3^ 3^5结果5
353=5
异或支持交换律的
异或只能用于整数操作
异或只会产生0和1,不会进位出现2,所以永远不会溢出

int main() {
	int a = 3;
	int b = 5;
	printf("交换前:a=%d b=%d\n", a, b);
	a = a ^ b;  
	b = a ^ b;      //b=a^b^b=a^0=a
	a = a ^ b;      //a=a^a^b=0^b=b   
	printf("交换后:a=%d b=%d\n", a, b);
}

C语言操作符详解(上)_第13张图片
编写代码实现:求一个整数存储在内存中的二进制中1的个数
思路点拨:

int main() {
	int a = 11;
	a & 1;
	//一个整数存储在内存中的二进制中1的个数
	//只要每次右移,每次和1按位与得到最后一位看一下是不是1
	a = a >> 1;
	//00000000 00000000 00000000 00001011
	//00000000 00000000 00000000 00000001
	//发现:最低位和1按位与,还是原来的数字
	//如果想要得到这个数的最低位是几,只要和1按位与就可以了
	//结果
	//00000000 00000000 00000000 00000001
}

四、赋值操作符

=

C语言操作符详解(上)_第14张图片
C语言操作符详解(上)_第15张图片

复合操作符

C语言操作符详解(上)_第16张图片

int main() {
	int a = 3;
	a = a + 3;
	a += 3;

	a = a ^ 5;
	a ^= 5;

	a = a >> 3;
	a >>= 3;

}

区分赋值和初始化:

int main() {
	int a = 3;//创建并初始化
	a = 5;//赋值
	return 0;
}

六、单目操作符

C语言操作符详解(上)_第17张图片
!的应用场景:

int main() {
	int flag = 5;
	if (flag) {  //flag为真做什么

	}
	if (!flag) {   //flag为假做什么

	}
	return 0;
}

&取地址操作符

int main() {
	int a = 10;
	&a;//&取地址操作符

	int arr[10];
	&arr;//取出数组的地址
}

解引用操作符(间接访问操作符)
*

int main() {
	int a = 10;
	int* p=&a;  //取地址操作符  p里面存的是a的地址
	*p = 20;   //解引用操作符(间接访问操作符)

	int arr[10];
	&arr;   //取出数组的地址

	return 0;
}

sizeof

int main() {
	int a = 10;
	printf("%d\n", sizeof(a));
	printf("%d\n", sizeof a);   //变量求长度时的小括号可以不写,但是int必须写
	printf("%d\n", sizeof(int));

	int arr[10] = { 0 };
	printf("%d\n", sizeof(arr));     //数组的长度
	printf("%d\n", sizeof(arr[0]));   //数组元素的长度
	int sz = sizeof(arr) / sizeof(arr[0]);    //数组元素的个数
	printf("%d\n", sz);
	return 0;

}

C语言操作符详解(上)_第18张图片
~的用法
对一个数的二进制位按位取反

int main() {
	int a = 0;
	//00000000 00000000 00000000 00000000
	//~a:按位取反
	//11111111 11111111 11111111 11111111 补码(内存里面的字都是补码)
	//11111111 11111111 11111111 11111110 反码
	//00000000 00000000 00000000 00000001  原码  -1
	printf("%d\n", ~a);   //-1

}

C语言操作符详解(上)_第19张图片
下面举例灵活应用单目操作符:

int main() {
	int b = 3;
	//00000000 00000000 00000000 00000011     b
	//如何把上面的数字倒数第四位变成1?

	//00000000 00000000 00000000 00000011      b
	//用b|
	//00000000 00000000 00000000 00001000     (1 << 3)
	b |= (1 << 3);
	//00000000 00000000 00000000 00001011     b=11
	printf("%d\n", b);  //11

	//如何将下面的数字
	//00000000 00000000 00000000 00001011
	//倒数第四位还原成0??
	//
	// 0&1=0 1&1=1
	// 所以将原数字与下面的数字按位与,就可以将倒数第四位还原成0
	//11111111 11111111 11111111 11110111  这个数字怎么表示呢?
	//我们发现它刚好是00000000 00000000 00000000 00001000     (1 << 3)取反可以得到
	//
	b &= (~(1 << 3));
	printf("%d\n", b);  //3


	return 0;
}

C语言操作符详解(上)_第20张图片
小知识点:
scanf读取失败的时候返回-1
原码
10000000 00000000 00000000 00000001
反码
11111111 11111111 11111111 11111110
补码
11111111 11111111 11111111 11111111
~按位取反之后:全0
00000000 00000000 00000000 00000000
此时就变成:
while(0)不进入循环,scanf读取失败
C语言操作符详解(上)_第21张图片
前置++ --:在使用之前++ - -
后置++ --:在使用之后++ - -

int main() {
	int a = 10;
	int b = a++;
	printf("%d\n", a);    
	printf("%d\n", b);  //后置++,先使用,再++
	//相当于int b=a;a=a+1;

}

C语言操作符详解(上)_第22张图片
后置++

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

C语言操作符详解(上)_第23张图片
前置++

int main() {
	int a = 10;
	printf("%d\n", ++a);  //先++,再使用
	printf("%d\n", a);
}

C语言操作符详解(上)_第24张图片
前置- -和后置- -同上面一个道理

(类型) 强制类型转换
仅仅是临时改变数据类型的一个状态

int main() {
	float a = 3.14f;
	int b = (int)a;  //强制性类型转换

	return 0;
}

sizeof()和数组
1.sizeof()内部单独放一个数组名,表示整个数组,所以(1)(3)处的值为40,10
2.注意:数组在传参的时候,实际上是传过去首元素的地址

void test1(int arr[])  //整形的地址放到整形的指针里面,int本质是int*,存放地址,指针变量的大小都是四个字节或者八个字节
{
	printf("%d\n", sizeof(arr));//(2)X86环境下指针的大小是4,X64环境下指针的大小是8
}
void test2(char ch[])   //char本质是char*,存放地址
{
	printf("%d\n", sizeof(ch));//(4)X86环境下指针的大小是4,X64环境下指针的大小是8
}
int main()
{
	int arr[10] = { 0 };
	char ch[10] = { 0 };
	printf("%d\n", sizeof(arr));//(1)  计算的是整个数组的大小:40
	printf("%d\n", sizeof(ch));//(3)   计算char类型的数组大小:10
	test1(arr);
	test2(ch);
	return 0;
}

七、关系操作符

在编程中注意==和=不要使用错误
C语言操作符详解(上)_第25张图片

八、逻辑操作符

C语言操作符详解(上)_第26张图片
&& 逻辑与 并且的意思 只关注真假
| | 逻辑或 或者的意思 只关注真假

& 按位与 二进制位进行计算
| 按位或 二进制位进行计算

int main() {
	int a = 3 && 5;
	int b = 3 && 0;
	printf("%d\n", a);
	printf("%d\n", b);

	int c = 1 || 0;
	int d = 0 || 0;
	printf("%d\n", c);
	printf("%d\n", d);


	return 0;
}

C语言操作符详解(上)_第27张图片
&& 操作符左边为假,右边不再计算
| | 操作符左边为真,右边不再计算

举例说明:

int main() {
	int i = 0, a = 0, b = 2, c = 3, d = 4;
	i = a++ && ++b && d++;  //0&&...a=0,后面不用计算

	printf("a=%d\nb=%d\nc=%d\nd=%d\n", a, b, c, d);
	return 0;

}

C语言操作符详解(上)_第28张图片

int main() {
	int i = 0, a = 1, b = 2, c = 3, d = 4;
	i = a++ && ++b && d++;  //1&&3&&4

	printf("a=%d\nb=%d\nc=%d\nd=%d\n", a, b, c, d);//2 3 3 5
	return 0;

}

C语言操作符详解(上)_第29张图片

int main() {
	int i = 0, a = 1, b = 2, c = 3, d = 4;
	i = a++ || ++b || d++;  //1||...或运算,左边有一个1,右边不用计算

	printf("a=%d\nb=%d\nc=%d\nd=%d\n", a, b, c, d);//2 2 3 4
	return 0;

}

C语言操作符详解(上)_第30张图片

int main() {
	int i = 0, a = 0, b = 2, c = 3, d = 4;
	i = a++ || ++b || d++;   //0||2...右边不用计算
	printf("a=%d\nb=%d\nc=%d\nd=%d\n", a, b, c, d);//1 3 3 4
	return 0;

}

C语言操作符详解(上)_第31张图片


这篇文章的内容你是否有所收获呢?小伙伴们,记得点赞收藏博客,关注后续的C语言操作符(下)内容哦~

你可能感兴趣的:(C语言,c语言,开发语言)