操作符详解(C语言所有基本操作符及其属性)

目录

1. 操作符的分类

2. 移位操作符

2.1 左移操作符

 2.2 右移操作符

3. 位操作符

练习1

练习2

练习3

4. 单目操作符

5. 逗号表达式

6. 下标引用操作符

7. 函数调用操作符

8. 结构成员访问操作符

8.1结构体成员的直接访问

8.2结构体成员的间接访问

9. 操作符的属性:优先级、结合性

9.1 优先级

 9.2 结合性


1. 操作符的分类

  • 算术操作符:+、-、*、/、%
  • 移位操作符:<<  、>>
  • 位操作符:&、 |  、^
  • 赋值操作符:= 、+=、-=、*=、/=、%=、<<=、>>=、&=、|=、^=
  • 单目操作符:!、++、--、&、*、+、-、~、sizeof、(类型)
  • 关系操作符:>、>=、<、<=、==、!=
  • 逻辑操作符:&&、||
  • 条件操作符:?、:
  • 逗号表达式:,
  • 下标引用:[ ]
  • 函数调用:()
  • 结构成员访问: .  、->

上述操作符中有一些与二进制有关系。

2. 移位操作符

<< 左移操作符

>> 右移操作符

注意:移位操作符的操作数只能是整数。

(移动的是二进制位的补码)

2.1 左移操作符

移位规则:左边抛弃、右边补0

#include<stdio.h>
int main()
{
	int num = 10;
	int n = num << 1;
	printf("num = %d\n", n);
	return 0;
}

左移操作符演示:

 

 2.2 右移操作符

移位规则:

右移运算分为两种:

  1. 逻辑右移:左边用0填充,右边丢弃。
  2. 算术右移:左边用原改值得符号位填充,右边丢弃。

注意:1、2两种用哪一个取决于编译器,但大部分是算术右移

#include<stdio.h>
int main()
{
	int num = 10;
	int n = num >> 1;
	printf("num = %d\n", n);
	return 0;
}


逻辑右移1位演示:

算术右移1为演示:

警告:对于移位运算符,不要移动负数位,这个是标准未定义的。

例如:

int num = 10;
num >> -1;

3. 位操作符

位操作符有:

1、&     按位与   (两个都为1才为1,有一个0则为0)

2、|       按位或   (有1则为1,两个都为0才为0)

3、^      按位异或   (相同为0,相异为1)

4、~      按位取反   (0变1,1变0,包括符号位)(单目操作符)

注意:他们的操作数必须是整数,作用的对象都是二进制补码。

代码:

#include<stdio.h>
int main()
{
	int num1 = -3;
	int num2 = 5;
	printf("num1 & num2 = %d\n", num1 & num2);
	printf("num1 | num2 = %d\n", num1 | num2);
	printf("num1 ^ num2 = %d\n", num1 ^ num2);
	printf("~num1 = %d\n", ~ num1);
	printf("~num2 = %d\n", ~ num2);

	return 0;
}

练习1

题目:编写代码求一个整数存储在内存中的二进制中1的个数。

#include<stdio.h>

int main()
{
	int n = 0;
	scanf("%d", &n);
	int count = 0;
	for (int i = 0; i < 32; i++)
	{
		if (n & (1 << i))
			count++;
	}
	printf("%d\n", count);
	return 0;
}

优化后的代码:

#include<stdio.h>
int main()
{
	int n = 0;
	scanf("%d", &n);
	int count = 0;
	while (n)
	{
		count++;
		n = n & (n - 1);
	}
	printf("%d\n", count);
	return 0;
}

n = n & (n - 1);这行代码的作用是将n的二进制表示中最右边的1变为0。这是一种常见的技巧,可以用来统计二进制表示中1的个数。

练习2

题目:将13二进制序列的第5位修改为1,然后再改为0。

  1. 132进制序列: 00000000000000000000000000001101
  2. 将第5位置为1后:00000000000000000000000000011101
  3. 将第5位再置为000000000000000000000000000001101

代码:

#include<stdio.h>
int main()
{
	int a = 13;
	a = a | (1 << 4);
	printf("%d\n", a);
	a = a ^ (1 << 4);
	printf("%d\n", a);
	return 0;
}

练习3

题目:不能创建临时变量(第三个变量),实现两个数的交换。

代码:

#include<stdio.h>
int main()
{
	int a = 10;
	int b = 20;
	a = a ^ b;
	b = a ^ b;//b = (a^b)^b
	a = a ^ b;//(a^b)^a
	printf("a = %d  b = %d\n", a, b);
	return 0;
}

a ^ a = 0 

a ^0 = a


4. 单目操作符

单目操作符(只需要一个操作数来执行特定的操作)

有这些:

!、++、--、&、~、*、+、-、sizeof、(类型)

其中注意(类型)表示类型转换操作符:可以将一个变量或表达式的类型转换为另一种类型。

当需要将一个变量或表达式的类型转换为另一种类型时,可以使用类型转换操作符。

例子:

#include <stdio.h>

int main() {
    int num1 = 10;
    int num2 = 3;
    float result;

    // 将整数除法的结果转换为浮点数
    result = (float) num1 / num2;

    printf("Result: %.2f\n", result);

    return 0;
}


5. 逗号表达式

exp1,exp2,exp3,...expn

  • 逗号表达式,就是用逗号隔开的多个表达式
  • 逗号表达式,从左向右依次执行。
  • 整个表达式的结果是最后一个表达式的结果
//代码1
int a = 1;
int b = 2;
int c = (a>b, a=b+10, a, b=a+1);//逗号表达式
c是13
//代码2
if (a =b + 1, c=a / 2, d > 0)
//代码3
a = get_val();
count_val(a);
while (a > 0)
{
 //业务处理
 a = get_val();
 count_val(a);
}
如果使⽤逗号表达式,改写:
while (a = get_val(), count_val(a), a>0)
{
 //业务处理
}

6. 下标引用操作符

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

int arr[10];//创建数组
arr[9] = 10;//实⽤下标引⽤操作符。
[ ]的两个操作数是arr和9。

7. 函数调用操作符

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

#include <stdio.h>
void test1()
{
 printf("hehe\n");
}
void test2(const char *str)
{
 printf("%s\n", str);
}
int main()
{
 test1(); //这⾥的()就是作为函数调⽤操作符。
 test2("hello bit.");//这⾥的()就是函数调⽤操作符。
 return 0;
}

8. 结构成员访问操作符

8.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;
}

使用方式:结构体变量.成员名

8.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;
}

使用方式:结构体指针 -> 成员名

综合举例:

#include <stdio.h>
#include <string.h>
struct Stu
{
 char name[15];//名字
 int age; //年龄
};
void print_stu(struct Stu s)
{
 printf("%s %d\n", s.name, s.age);
}
void set_stu(struct Stu* ps)
{
 strcpy(ps->name, "李四");
 ps->age = 28;
}
int main()
{
 struct Stu s = { "张三", 20 };
 print_stu(s);
 set_stu(&s);
 print_stu(s);
 return 0;
}

9. 操作符的属性:优先级、结合性

C语⾔的操作符有2个重要的属性:优先级、结合性,这两个属性决定了表达式求值的计算顺序。

9.1 优先级

优先级指的是,如果⼀个表达式包含多个运算符,哪个运算符应该优先执行。各种运算符的优先级是不⼀样的。
3 + 4 * 5;
表达式 3 + 4 * 5 中 既有加法运算符( + ),又有乘法运算符( * )。由于乘法
的优先级高于加法,所以会先计算 4 * 5 ,而不是先计算 3 + 4

 9.2 结合性

如果两个运算符优先级相同,优先级没办法确定先计算哪个了,这时候就看结合性了,则根据运算符是左结合,还是右结合,决定执行顺序。大部分运算符是左结合(从左到右执行),少数运算符是右 结合(从右到左执行),比如赋值运算符( = )。
5 * 6 / 2;
上面示例中, * 和 / 的优先级相同,它们都是左结合运算符,所以从左到右执行,先计算 5 * 6 再计算 6 / 2

 运算符的优先级顺序很多,下面是部分运算符的优先级顺序(按照优先级从高到低排列

圆括号( ()
• 自增运算符( ++ ),自减运算符( --
单目运算符( + -
乘法( * ),除法( /
加法( + ),减法( -
关系运算符( < > 等)
赋值运算符( =
由于圆括号的优先级最高,可以使用它改变其他运算符的优先级。

下面是所有操作符的优先级表


完 

  • 43
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值