C语言入门系列5-操作符-适合C语言初学者了解运算符(操作符)的用法,结合性,优先级-同样适合期末考复习操作符部分的内容


前言

本篇介绍操作符相关的知识,包括操作符的种类、用法、优先级、结合性


一、运算符符的种类

C 语言内置了丰富的运算符,大致将其分为以下六类:算术运算符、赋值运算符、逻辑运算符、关系运算符、位运算符和其他运算符。


二、算数运算符

+ - * / %

1.对于%,它的两个操作数必须为整数,其他四个都能作用于浮点数和整数,返回结果为余数,如5%2=1
2.对于/,如果两个操作数都是整数,那么执行整数除法,如5/2=2,如果有一个操作数为浮点数,执行浮点数除法,如5/2.0=2.5


三、位运算符

1.移位运算符 >><<

<<左移运算符
>>右移运算符

注意:移位运算符的操作数只能是整数!!!
<<左移规则:左边抛弃,右边补零,下面举例

             //以整形在内存中的存储为32位举例,10的二进制表示为1010
int num = 10;//00000000 00000000 00000000 00001010
num <<= 1    //00000000 00000000 00000000 00010100

>> 右移规则:右边抛弃,左边有可能补零,有可能按符号位补齐
在C语言中,右移运算符>>将一个数的二进制表示向右移动指定的位数,移动时保持符号位不变,即如果该数的符号位为1,则移动后在左侧补1,如果符号位为0,则移动后在左侧补0。
因此,对于-1(其二进制表示为全1),进行右移操作后,得到的结果应为1111…111(根据所使用的机器字长而定)。因为符号位为1,所以在移位时左侧会一直补1,直到移位结束。
移动的位数大于或等于操作数的位数时,其结果是未定义的,不确定的,这是因为C语言规范并没有定义这种情况应该如何处理。实际上,这种情况可能会导致不同的结果,具体的行为取决于所使用的编译器和机器的架构。
因此,在编写代码时,应该避免移动的位数大于或等于操作数的位数,以避免出现未定义的行为。
如果1111…1111(二进制)是一个无符号整数,并进行右移操作,那么高位将始终填充0。
总结:右移操作时情况复杂,需要对具体情况分析,还有可能出现未定义行为,此时需要小心使用

2.& | ^ ~

在C语言中,&、|、^和~都是位运算符,可以用来操作二进制位。

&(按位与):将两个操作数的二进制位进行与运算,只有当两个位都为1时,结果才为1,否则为0。
例如, 1101 & 1010 = 1000。
|(按位或):将两个操作数的二进制位进行或运算,只有当两个位都为0时,结果才为0,否则为1。
例如, 1101 | 1010 = 1111。
^(按位异或):将两个操作数的二进制位进行异或运算,只有当两个位不同时,结果才为1,否则为0。
例如, 1101 ^ 1010 = 0111。
~(按位取反):将操作数的二进制位进行取反运算,即0变为1,1变为0。
例如, ~1101 = 0010。


四、赋值运算符

最简单的有=
复合运算符有+= -= /= *= %= <<= >>= &= |= ^=

int x = 10;
x = x+10;
x += 10;//复合赋值
//其他运算符一样的道理。这样写更加简洁。

五、逻辑运算符

在C语言中,逻辑运算符用于对逻辑值(true或false)进行操作。C语言中的逻辑运算符有三个:&&(逻辑与)、||(逻辑或)和!(逻辑非)。

&&(逻辑与):当两个操作数都为真(即非零)时,结果为真;否则结果为假(即零)。例如,if(a && b)表示当a和b都为真时执行if语句。
||(逻辑或):当两个操作数中有一个为真时,结果为真;否则结果为假。例如,if(a || b)表示当a或b有一个为真时执行if语句。
!(逻辑非):操作数为真时,结果为假;操作数为假时,结果为真。例如,if(!a)表示当a为假时执行if语句。

需要注意的是,逻辑运算符的操作数只能是逻辑值(true或false),C语言中0表示假,非零表示真。在使用逻辑运算符时,还需要遵循C语言中的短路规则:当使用&&运算符时,如果第一个操作数为假,则不会执行第二个操作数;当使用||运算符时,如果第一个操作数为真,则不会执行第二个操作数。这种规则可以避免不必要的运算和提高程序效率。

下面用两段代码举例解释

int main()
{
    int i = 0, a = 0, b = 2, c = 3, d = 4;
    i = a++ && ++b && d++;
    printf("a = %d\nb = %d\nc = %d\nd = %d\n", a, b, c, d);
    return 0;
}
//程序输出的结果是什么?

在这里插入图片描述

下面对结果进行分析,从左到右执行,a++返回值为0,所以截断,不再执行++b和d++,但a已经变为1,所以输出1、2、3、4

#include <stdio.h>
int main()
{
    int i = 0, a = 0, b = 2, c = 3, d = 4;
    i = a++ || ++b || d++;
    printf("a = %d\nb = %d\nc = %d\nd = %d\n", a, b, c, d);
    return 0;
}

在这里插入图片描述
这里同理,在++b处发生截断,所以d++不再执行


六、关系运算符

在C语言中,关系运算符用于比较两个值之间的关系,结果为逻辑值(true或false)。C语言中的关系运算符包括:==(等于)、!=(不等于)、>(大于)、>=(大于等于)、<(小于)和<=(小于等于)。

==(等于):当两个操作数相等时,结果为真;否则结果为假。例如,if(a == b)表示当a等于b时执行if语句。
!=(不等于):当两个操作数不相等时,结果为真;否则结果为假。例如,if(a != b)表示当a不等于b时执行if语句。

>(大于):当左操作数大于右操作数时,结果为真;否则结果为假。例如,if(a > b)表示当a大于b时执行if语句。
>=(大于等于):当左操作数大于等于右操作数时,结果为真;否则结果为假。例如,if(a >= b)表示当a大于等于b时执行if语句。

<(小于):当左操作数小于右操作数时,结果为真;否则结果为假。例如,if(a < b)表示当a小于b时执行if语句。
<=(小于等于):当左操作数小于等于右操作数时,结果为真;否则结果为假。例如,if(a <= b)表示当a小于等于b时执行if语句。

关系运算符通常用于比较数值、判断大小关系和排序等方面。需要注意的是,关系运算符的操作数可以是任意类型的,但要求两个操作数的类型相同,否则会进行类型转换。


七、其他运算符

1.单目运算符

+(正号):对操作数不做任何改变,返回操作数的值。例如,+a表示a的值。
-(负号):将操作数取反,返回相反数的值。例如,-a表示a的相反数。
!(逻辑非):操作数为真时,结果为假;操作数为假时,结果为真。例如,!a表示a的逻辑非值。
&(取地址):返回操作数的地址。例如,&a表示a的地址。
*(解引用):返回指针所指向的值。例如,*p表示指针p所指向的值。
sizeof:用于计算数据类型或变量的字节大小,其语法为sizeof(type)或sizeof(variable)
~是一种单目运算符,同时也是位运算符,上面讲解过,这里不再赘述
--和++:它们都是用于递增或递减变量的操作符,称为自增运算符和自减运算符。它们都可以作为前缀或后缀使用。前缀运算符表示在表达式中使用变量之前进行递增或递减操作,而后缀运算符则表示在表达式中使用变量之后进行递增或递减操作。
(类型):类型转换运算符,也称为强制类型转换运算符或显式类型转换运算符。

2.下标引用[]、函数调用()和结构成员. ->

(1)[]使用方式:array[index]

(2)()使用方式:

function_name(argument1, argument2, …, argumentN)
其中,function_name是函数名,argument1、argument2等是传递给函数的参数。函数调用会执行函数内部的代码,并返回函数的返回值(如果有的话)。

#include <stdio.h>
 void test1()
 {
 	printf("123456\n");
 }
 void test2(const char *str)
 {
 	printf("%s\n", str);
 }
 int main()
 {
	 test1();            //实用()作为函数调用操作符。
	 test2("c language programming");//实用()作为函数调用操作符。
	 return 0;
 }

(3).->

#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);
	 
	 pStu->age = 20;//通过指针进行结构成员访问
	 set_age2(pStu);
	 return 0;
}

八、隐式转换

1.整型提升

//实例1
char a,b,c;
b = 10;
c = 20;
a = b + c;

b和c的值被提升为普通整型,然后再执行加法运算。
加法运算完成之后,结果将被截断,然后再存储于a中。
整形提升是按照变量的数据类型的符号位来提升的
整形提升的规则类似于>>操作符,高位都是按照符号位来补
下面举例

//例1
int main()
{
	char a = 0xb5;
	short b = 0xb500;
	int c = 0xb5000000;
	if (a == 0xb5)
		printf("a");
	if (b == 0xb500)
		printf("b");
	if (c == 0xb5000000)
		printf("c");
	return 0;
}

程序输出为c,这是因为a和b都发生了整型提升,而符号位为1,所以截断之后变成负数

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

输出为1 4 4,因为a一旦参与运算则发生整型提升

2.隐式类型转换

#include <stdio.h>
int main()
{
	int a = 0;
	long long b = 1;
	a = sizeof(1 ? a : b);
	printf("%d\n", a);
	return 0;
}

a的输出结果为8,因为发生了隐式类型转换,变为long long类型
再如

float f = 3.14;
int num = f;//隐式转换,会有精度丢失

num的值为3
下面给出转换的优先级,从高到低
long double
double
float
unsigned long int
long int
unsigned int
int


九、运算符优先级与结合性

在这里插入图片描述

需要注意的是,括号可以用来改变运算符的优先级和结合性,因此可以通过使用括号来明确计算顺序。另外,在使用运算符的过程中,还需要注意一些运算符的副作用,例如递增/递减运算符会改变变量的值,应该避免在表达式中多次使用它们。


总结

在使用运算符时需要注意它们的优先级和结合性,以及一些特殊的运算方式和副作用。正确使用运算符可以使代码更加清晰和易于理解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值