操作符详解 (7.23)

本文详细介绍了C语言中的各种操作符,包括算术操作符、移位操作符(算术右移和逻辑右移)、位操作符(按位与、按位或、按位异或)、赋值操作符以及单目操作符。特别强调了移位操作只适用于整数且负数位移未定义,位操作符的作用,以及sizeof运算符的使用和陷阱。文章还涵盖了逻辑操作符的短路行为,条件操作符和逗号表达式的用法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文章目录

一、操作符介绍

1、算术操作符

插图 6‘

2、移位操作符 (只能作用于整数,不能作用于浮点数)

移位时移动的是补码

右移的两种移动方法:

在这里插入图片描述

(1)算术右移:(通常情况使用)(右移则其数值除2)

右边丢弃,左边补充原符号位
原来正数补0;
原来负数补1.

(2)逻辑右移:(数值乘2的效果)

右边丢弃,左边补0

左移:左边丢弃,右边补0

在这里插入图片描述

注意事项:
对于移位运算操作符,不要移动负数位,该标准未定义。
例如:

int main()
{
	int num=10;
	num>>-1;   //error
	return 0;
}

3、位操作符(只能作用于整数,不能作用于浮点数)

(1)&, 按位与 (二进制位)

(2)|, 按位或 (二进制位)

(3)^, 按位异或 (二进制位):

相同为0,不同为1(任何数和0异或为其本身)

//按位与
int main()
{
	int a=10;   //00000000000000000000000000001010
	int b=20;   //00000000000000000000000000010100
	int c=a&b;    //是32位二进制数字“与”,二进制数字同1则1,反之为0,“与”后结果为00000000000000000000000000000000
	printf("c=%d\n",c);  //输出值为0
	return 0;
}

//按位或
int main()
{
	int a=10;   //00000000000000000000000000001010
	int b=20;   //00000000000000000000000000010100
	int c=a|b;    //是32位二进制数字“与”,二进制数字有1则1,全0为0,“或”后结果为00000000000000000000000000011110
	printf("c=%d\n",c);  //输出值为由二进制转换为十进制为30
	return 0;
}

//按位异或
int main()
{
	int a=10;   //00000000000000000000000000001010
	int b=20;   //00000000000000000000000000010100
	int c=a^b;    //是32位二进制数字“与”,二进制数字不同为1,相同为0,“或”后结果为00000000000000000000000000011110
	printf("c=%d\n",c);  //输出值为由二进制转换为十进制为30
	return 0;
}

4、赋值操作符(1h14‘)

前面可以先定义一个值,后面不满意再重新赋值(使用赋值操作符赋值)(一个“=”号)
在这里插入图片描述

(1)连续赋值(不建议使用)

(2)复合赋值符1h15’

a=a+2 等价于 a+=2
a=a>>1 等价于 a>>=1
a=a&1 等价于 a&=1

5、单目操作符

(1)! ,真变假,假变真

int main()
{
	int a=0;
	if(!a)
	{
		printf("hehe\n");
	}
	return 0;
}

(2)sizeof

举例1:
int main()
{
	int a=0;
	char b='r';
	char* p=&c;
	int arr[10]={0};
	printf("%d\n",sizeof(a));    //整型4个字节   a的括号可以省略
	printf("%d\n",sizeof(int));    //整型4个字节,括号不可省略

	printf("%d\n",sizeof(c));    //char类型占用1字节
	printf("%d\n",sizeof(char));    //char类型占用1字节

	printf("%d\n",sizeof(p));    //32位系统,指针占用4字节
	printf("%d\n",sizeof(char*));    //32位系统,指针占用4字节

	printf("%d\n",sizeof(arr));  //整型数组,其中10个元素,每个元素4字节,共计40字节
	printf("%d\n",sizeof(int [10]));  //整型数组,其中10个元素,每个元素4字节,共计40字节,对于数组也可以用类型来计算


	return 0;
}
举例2:(易错)关于sizeof(arr)和函数调用

(7.24日 始)

void test1(int arr[])    //数组传参时,传递数组的首元素地址,此时arr为指针
{
	printf("%d\n",sizeof(arr));  //  指针大小只有4字节(32位)/8字节(64位)
}
void test2(char ch[])   //数组传参时,传递数组的首元素地址,所以此时的ch为指针
{
	printf("%d\n",sizeof(ch));  //  指针大小只有4字节(32位)/8字节(64位)
}

int main()
{	
	int arr[10]={0};
	char ch[10]={0};
	printf("%d\n",sizeof(arr));    //输出为整个整型数组的所占空间大小,4*10=40
	printf("%d\n",sizeof(ch));     //输出为整个字符数组所占空间大小,1*10=10
	test1(arr);
	test2(ch);
	return 0;
}

(3)按位取反(~)

int main()
{
	int a=0;
	//按位(2进制)取反
	//0的二进制 00000000000000000000000000000000(补码)
	//取反 11111111111111111111111111111111(补码)
	// 11111111111111111111111111111110(反码) (补码+1)
	// 10000000000000000000000000000001(原码)(反码取反,符号位不变)   得值为-1
	
	printf("%d\n",~a);//内存存储为补码,打印出的为原码
	return 0;
}

(4)++和- -

前置:先++,后使用
后置

int main()
{
	int a=10;
	printf("%d\n",++a);  //先+ ,再打印,得值为11
	printf("%d\n",a++);  //先打印,再+,与上方分别打印时,得值为10
	//如果两项一起打印时,都得值为11,因为上方a打印后自增1,所以a值变为11
	return 0;
}

(5)* 间接引用操作符(解引用操作符)

(6)(类型)强制转换类型

int main()
{
	int a=(int)3.14;
	//int a=int(3.14) error
	return 0;
}

6、关系操作符

36‘50’‘

7、逻辑操作符

37’18‘’

(1)逻辑与&&:全真为真,一假则假

特点:左边为假时,右边无论是什么都不进行计算

举例1:(普通的逻辑与和逻辑或)
int main()
{
	int a=1;
	int b=2;
	int c=a&&b;
	int d=a||b;
	printf("%d\n",c);    //“逻辑与”,全真为真,输出1
	printf("%d\n",d);    //“逻辑或”,一真则真,全假为假,输出1
}
举例2:(易错点:“逻辑与”有一次判断为假时,后边无论是什么都不进行计算)
int main()
{
	int i=0,a=0,b=2,c=3,d=4;
	i=a++ && ++b && d++;   //a++,先用再自增,此时a=0.左边为假,右边不进行计算
	printf("a=%d\n b=%d\n c=%d\n d=%d\n",a,b,c,d); //输出值为1234
	return 0;
}

**(2)逻辑或||:**一真则真,全假则假

举例:(易错点:“逻辑或”有一次判断为真时,后边无论是什么都不进行计算)
int main()
{
	int i=0,a=1,b=2,c=3,d=4;
	i=a++ || ++b || d++;   //a++,先用再自增,此时a=1.第一次判断为真,右边不进行计算
	printf("a=%d\n b=%d\n c=%d\n d=%d\n",a,b,c,d); //输出值为2234
	return 0;
}

8、条件操作符

exp1?exp2,exp3

含义:判断表达式1真假,1为真时,执行表达式2;1为假时,执行表达式3

int main()
{
	int a=10;
	int b=20;
	int max=0;
	if(a>b)
		max=a;
	else
		max=b;
	printf("max =%d\n",max);
	return 0;
}

等价于下方代码

int main()
{
	int a=10;
	int b=20;
	int max=0;
	max=(a>b?a:b);
	printf("max =%d\n",max);
	return 0;
}

9、逗号表达式

整个表达式从左至右依次计算,但是表达式的结果为最后一个表达式的结果

插图1h15‘32’‘
3个代码

int main()
{
	int a=1;
	int b=2;
	int c=(a>b,a=b+10,a,b=a+1);      //a>b为假,不执行;a=2+10=12; b=12+1=13,然后将b的值赋值给c
	printf("%d\n",c);
	return 0;
}

在这里插入图片描述

在这里插入图片描述

10、下标引用、函数调用、结果成员操作符

(1)下标引用操作符

1h18’14‘’

操作数:一个数组名+一个索引值

(2)函数调用操作符

一般调用自定义函数的时候“()”就是函数调用操作符
至少有一个操作数,即为函数操作名

int get_max(int x,int y)
{
	return (x>y?x:y);
}
int main()
{
	int a=10;
	int b=20;
	int max=get_max(a,b); //  此处的()为函数调用操作符,其操作数为 get_max,a,b  至少有一个操作数,即为函数操作名
	
	printf("max =%d\n",max);
	return 0;
}

(3)访问一个结构的成员

“.” 结构体.成员名

结构体变量.成员名

//创建结构体类型--struct stu
struct stu
{
//成员变量
	char name[20];
	int age;
	char id[20];
};
int main()
{
	int a=10;
	//使用struuct stu类型创建了一个学生对象s1,并初始化
	struct stu s1={"张三",20,"20180109"};
	printf("%s\n",s1.name);
	printf("%d\n",s1.age);
	printf("%d\n",s1.id);
	return 0;
}

“->” 结构体指针->成员名

struct stu
{
	char name[20];
	int age;
	char id[20];
};
int main()
{
	int a=10;
	//使用struuct stu类型创建了一个学生对象,并初始化
	struct stu s1={"张三",20,"20180109"};
	struct stu* ps=&s1;
	printf("%d\n",ps->age);   //左边为结构体指针,右边是成员名
	printf("%d\n",ps->id);            
	printf("%s\n",ps->name);
	return 0;
}

二、表达式求值

1h34‘47’‘

隐式类型转换

整型提升

插图 1h55‘43’‘
参与计算的变量 没有达到整型大小,都会整型提升

在这里插入图片描述

算术转换

插图 1h56’22‘’

三、操作符的属性

1、操作符的优先级

优先级由上至下
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2、操作符的结合性

一些问题表达式(无法确定计算的唯一路径):

例如:ab+cd+e*f
在这里插入图片描述

c±-c(–优先级高于+)
插图2h23’41‘’

代码3

代码4(2h26‘)
在这里插入图片描述

3、是否控制求值顺序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值