C语言应该怎么玩——操作符总结

1、算数操作符

+    -    *    /    %

这里提一下 / 和 % :

/和数学里的除号运算方式不太一样。C语言中,整数/整数,得到的结果还是整数。要想得到的结果为实数,/两端的数据至少一个为实数类型。

    int a = 1 / 2;
	printf("%d\n", a);//显示结果为0
	double b = 1.0 / 2;
	printf("%lf\n", b);//显示结果为0.500000

%是取模操作符,就是求余数。%操作符的两个操作数必须是整数,即整数%整数

    int a = 3 % 2;
	printf("%d\n", a);//显示结果为1
	int b = 3.0 % 2;//error

2、移位操作符

<<     左移操作符
>>     右移操作符

<< 左移操作符规则:左边丢弃,右边补0

	int a = 2;
	int b = a << 1;
	printf("%d\n", b);//显示结果为4

左移过程
左移操作符的规则通过图示比较好理解,但是右移操作符的规则与左移操作符的规则不完全一样。在介绍之前先了解一下原码、反码、补码的概念。
在这里插入图片描述
了解原码、反码、补码的概念后,接下来介绍右移操作符的规则:

>>右移操作符规则:
1、算数右移:右边丢弃,左边补原符号位
2、逻辑右移:右边丢弃,左边补0 (到底是算术右移还是逻辑右移,取决于编译器)

	int a = -1;
	int b = a >> 1;
	printf("%d\n", b);//显示结果为-1

(vs2022采用的是算数右移)
在这里插入图片描述
由于了解了原码、反码、补码,可以知道左移操作符、右移操作符移动的都是数的补码,而输出的是数的原码,所以在进行移位操作后别忘了将补码转换为原码
注意:
int a = -1;
int b = a >> 1;
printf(“%d\n”, b);//显示结果为-1
(这里对a进行右移操作,只是把得到的结果赋给b,a本身并不发生值的变化。)

3、位操作符

&     按位与  
|     按位或  
^     按位异或

& 按位与:两个条件同时为真(1),结果才为真(1),条件中有一个为假(0),结果就为假(0)

	int a = 3;
	int b = 5;
	int c = a & b;
	printf("%d\n", c);//显示结果为1

在这里插入图片描述

| 按位或:两个条件有一个为真(1),结果就为真(1),两个条件都为假(0),结果才为假(0)

	int a = 3;
	int b = 5;
	int c = a | b;
	printf("%d\n", c);//显示结果为7

在这里插入图片描述

^ 按位异或:两个条件一真(1)一假(0),结果才为真(1),就是对应的二进制位,相异为真(1),相同为假(0)。

	int a = 3;
	int b = 5;
	int c = a ^ b;
	printf("%d\n", c);//显示结果为6

在这里插入图片描述

4、赋值操作符

=
+=
-=
*=
/=
%=
>>=
<<=
&=
|=
^=

符合赋值符的概念很简单,但是作用很大。这里简单提一下,以 += 为例:

	int a = 10;
	a = a + 100;//1
	a += 100;  //2    1和2是等价的

其他复合赋值符也类似。
注意:
=是赋值;==是判断,判断是否相等。

5、单目操作符

!          逻辑反操作  
-           负值     
+           正值   
&           取地址  
sizeof      求操作数的类型长度(以字节为单位)  
~           对一个数的二进制按位取反  
--          前置、后置--  
++          前置、后置++  
*           间接访问操作符(解引用操作符)  
(类型)    强制类型转换

! 逻辑反操作

逻辑反操作符就是把真变假,把假变真。

	int a = 5;
	//a为真,打印hehe
	if (a)
	{
		printf("hehe\n");
	}
	//a为假,打印haha
	if (!a)
	{
		printf("haha\n");
	}
	//显示结果为hehe

补充:德摩根定律:对各条件取非,然后将逻辑与变为逻辑或、逻辑或变为逻辑与,然后再取否定,结果和原条件一样,即:
x && y和! (!x || !y)相等
x || y和! (!x && !y)相等

sizeof 求操作数的类型长度(以字节为单位)

	int a = 10;
	//计算a所占内存空间的大小,单位是字节
	printf("%d\n", sizeof(a));//显示结果为4
	//计算int类型的大小,单位是字节
	printf("%d\n", sizeof(int));//显示结果为4

	int arr[10] = { 0 };
	//计算整个数组所占内存空间的大小,单位是字节
	//数组名arr单独放在sizeof,代表的是整个数组
	printf("%d\n", sizeof(arr));//显示结果为40
	//计算数组类型int [10]的大小,单位是字节
	printf("%d\n", sizeof(int [10]));//显示结果为40

sizeof是一个操作符,不是函数!

这里思考一个代码:

	short s = 5;
	int a = 10;
	printf("%d\n", sizeof(s = a + 2));//显示结果为2
	printf("%d\n", s);//显示结果为5

解释:
第一个显示结果:s是short型,只占2个字节,即使a+12的结果是int型,但s所占的内存空间只有2个字节,所以sizeof所测的数据类型由s决定,s是short类型,占2个字节,所以显示结果为2。
第二个显示结果:放在sizeof()里面的表达式是不参与运算的。我们编写的源文件(test.c)变成可执行程序(test.exe)需要经过编译、链接、运行,sizeof()中的s=a+2在编译期间已经处理过了,所以在运行期间s=a+2这个表达式不会进行计算,因此a+2的值不会赋给s,由于a+10的值没有赋给s,所以显示结果为5。

~ 对一个数的二进制(补码)按位取反

	int a = -1;
	int b = ~a;
	printf("%d\n", b);//显示结果为0

在这里插入图片描述

- - 前置、后置- -
++ 前置、后置++

++前置:先++,再使用
后置++:先使用,再++
(- -前置、后置- -同理)

	int a = 10;
	int b = ++a;
	printf("%d\n", b);//显示结果为11
	printf("%d\n", a);// 显示结果为11

	int a = 10;
	int b = a++;
	printf("%d\n", b);//显示结果为10
	printf("%d\n", a);// 显示结果为11

    int a = 10;
	printf("%d\n", a--);//显示结果为10
	printf("%d\n", a);//显示结果为9

这里吐槽一个(妖魔化的)代码:

在这里插入图片描述

结果就不说了,不同的编译器结果是不一样的。

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

1|	int a = 10;
2|	int* pa = &a;
3|	*pa = 20;
4|	printf("%d\n", a);//显示结果为20

代码解释:
第2行:&a是把a的地址取出来,int表明pa是一个指针变量,不是解引用操作符的意思,所以这行代码的意思是用&把a的地址取出来,通过=把地址存进指针变量pa里。
第3行:*pa中的*是解引用操作符,*pa的意思是通过pa中存储的地址找到它所指向的对象,也就是a。

(类型) 强制类型转换

	int a = (int)3.14;
	printf("%d\n", a);

3.14是double型, 如果要把3.14强制放到int型的a里面的话会有警告,而(int)3.14把3.14强制转换成int型,这时候把值存进a里就不会报警告了。

通过上面的介绍,发现这些操作符的操作数只有一个,所以叫单目操作符,因此单目操作符中的 + -表示的是数值的正负,而双目操作符里的+ -表示的是加减运算。

6、关系操作符

>
>=
<
<=
!=    用于判断是否不相等
==    用于判断是否相等

再次强调:
=是赋值; ==是判断,判断是否相等。

7、逻辑操作符

&&    逻辑与
||    逻辑或

&&逻辑与表示的意思是并且||逻辑或表示的意思是或者。这两个操作符用于表示逻辑上的真假。

a && b只有a、b同时为真,逻辑结果才为真。

	int a = 3;
	int b = 0;
	if (a && b)
		printf("逻辑为真\n");//不打印

a || b只要有一个为真,逻辑结果就为真。

	int a = 3;
	int b = 0;
	if (a || b)
		printf("逻辑为真\n");//显示结果为逻辑为真

这里思考两个代码:

	int i = 0, a = 0, b = 2, c = 3, d = 4;
	i = a++ && ++b && d++;
    printf("a=%d b=%d c=%d d=%d\n", a, b, c, d);
	int i = 0, a = 0, b = 2, c = 3, d = 4;
	i = a++ || ++b || d++;
	printf("a=%d b=%d c=%d d=%d\n", a, b, c, d);
//第一个代码的显示结果为a=1 b=2 c=3 d=4
//第二个代码的显示结果为a=1 b=3 c=3 d=4

解释:
逻辑运算符会改变运算的顺序。
例1:
expr1 && expr2 && expr3,当表达式expr1结果假时,整个expr1 && expr2 && expr3的结果已经为假,所以表达式expr2、expr3不会有机会进行运算,也就是不执行这两个表达式;当表达式expr1为真时,expr2就有机会参与运算并判断真假。
例2:
expr1 || expr2 || expr3,当表达式expr1结果真时,整个expr1 && expr2 && expr3的结果已经为真,所以表达式expr2、expr3不会有机会进行运算,也就是不执行这两个表达式;当表达式expr1为假时,expr2就有机会参与运算并判断真假。

8、条件操作符

表达式1 ?表达式2 :表达式3

条件操作符又叫三目操作符,它是唯一一个有三个操作数的操作符。那这个操作符是什么意思呢?
expr1 ? expr2 : expr3
解释:首先对expr1的结果进行判断,如果判断结果为真,直接执行expr2,跳过expr3;如果判断结果为假,直接执行expr3,跳过expr2。

	int a = 3;
	int b = 0;
	//代码1  if语句
	if (a > 5)
		b = 1;
	else
		b = -1;
	//代码2  条件操作符
	b = (a > 5 ? 1 : -1);

代码1和代码2表示的意思是一样的。

9、逗号表达式

表达式1,表达式2,表达式3,··· 表达式n

逗号表达式,要从左向右依次计算。整个表达式的结果是最后一个表达式的结果。

	int a = (1, 2, 3, 4);
	printf("%d\n", a);//显示结果为4

这里再提供一个代码和它的运行结果,代码比较简单,就不做解释了。

在这里插入图片描述

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

[ ] 下标引用操作符

所谓的下标引用操作符,就是通过下标来访问数组里的元素。
操作数:一个数组名 + 一个索引值

1|	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
2|	printf("%d\n", arr[4]);//显示结果为5

第一行代码中的[ ]是在定义数组的时候指定数组大小的一种语法格式;
第二行代码中的[ ]就是我们的下标引用操作符。

( ) 函数调用操作符

( ) 函数调用操作符在我们的代码中是非常常见的,无论是最常见的main函数(主函数),或者是库函数,自定义函数等,都会有( )的身影。

( ) 函数调用操作符接受一个或者多个操作数:第一个操作数是函数名,剩余的操作数就是传递给函数的参数。

int Add(int x, int y)
{
	return x + y;
}

int main()
{
	int a = 10;
	int b = 20;
	int ret = Add(a, b);
	printf("%d\n", ret);//显示结果为30

	return 0;
}

访问一个结构的成员:
.
->

. 的使用形式:结构体变量名.成员名
-> 的使用形式: 结构体指针->成员名
(1)代码演示 . 的使用形式:

struct Book
{
	char name[20];
	char id[20];
	int price;
};

int main()
{
	struct Book b = { "C语言", "20221002", 55 };
	printf("书名:%s\n", b.name);//显示结果为 书名:C语言
	printf("书号:%s\n", b.id);//显示结果为 书号:20221002
	printf("定价:%d\n", b.price);//显示结果为 定价:55

	return 0;
}

(2)代码演示 -> 的使用形式:

struct Book
{
	char name[20];
	char id[20];
	int price;
};

int main()
{
	struct Book b = { "C语言", "20221002", 55 };
	struct Book* pb = &b;
	printf("书名:%s\n", pb->name);//显示结果为 书名:C语言
	printf("书号:%s\n", pb->id);//显示结果为 书号:20221002
	printf("定价:%d\n", pb->price);//显示结果为 定价:55

	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值