C语言 运算符

一、算数运算符

算数运算符有: +  -   *   /   % 五种。由于运算符有两个操作数。也被称为双目运算符

对于 / 运算符,两个操作数都是整数执行的是整数除法。至少有一个操作数是浮点时执行浮点除法

#include <stdio.h>
int main() {
	int i = 5 / 2;
	printf("%d\n", i);
	return 0;
}

输出

2
#include <stdio.h>
int main() {
	double i = 5.0 / 2;
	printf("%lf\n", i);
	return 0;
}

输出

2.500000

%运算符的两个操作数必须为整数,返回的是整除后的余数

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

对于 a / b ,运算符两个操作数有一个是负数时。如果左操作数是负数,结果为:-((-a) / b)。如果右操作数是负数,结果为:-(a / (-b))

#include <stdio.h>
int main() {
	int i = -7 / 3;
	int j = 5 / -2;
	printf("-7 / 3 = %d\n", i);
	printf("5 / -2 = %d\n", j);
	return 0;
}

输出

-7 / 3 = -2
5 / -2 = -2

对于 a % b ,运算符两个操作数有一个是负数时。如果左操作数是负数,结果为:-((-a) % b)。如果右操作数是负数,结果为:a % (-b)

#include <stdio.h>
int main() {
	int i = -7 % 2;
	int j = 5 % -2;
	printf("-7 %% 2 = %d\n", i);
	printf("5 %% -2 = %d\n", j);
	return 0;
}

输出

-7 % 2 = -1
5 % -2 = 1

二、移位运算符

前言:整数在内存中存储的是二进制。存储有符号整数时将二进制最高位设定为符号位,1表示负数,0表示正数。一个整数二进制表示形式有原码、反码、补码。正整数的原码、反码、补码都相同负整数的原码、反码、补码需要计算使用、打印整数时使用原码,计算时使用补码

int i = 10; //正整数的原码、反码、补码都相同
00000000 00000000 00000000 00001010  //10的原码
00000000 00000000 00000000 00001010  //10的反码
00000000 00000000 00000000 00001010  //10的补码

int j = -1 
10000000 00000000 00000000 00000001  //-1的原码,即将-1化为二进制,最高位用1表示负数
11111111 11111111 11111111 11111110 //-1的反码,符号位不变,原码其他位按位取反
11111111 11111111 11111111 11111111 //-1的补码,反码+1

2.1左移运算符 <<

语法: 数字 << n
对数字的补码向左边移动n位,即左边抛弃,右边补0

#include <stdio.h>
int main() {
	int i = 10 << 2;
	//00000000 00000000 00000000 00001001   原码
	//00000000 00000000 00000000 00001001   反码
	//00000000 00000000 00000000 00001001   补码
	//00000000 00000000 00000000 00100100  对补码左移2位,右边补2个0
	printf("%d\n", i);
	return 0;
}

输出

40
#include <stdio.h>
int main() {
	int i = -1 << 2;
	//10000000 00000000 00000000 00000001   -1原码
	//11111111 11111111 11111111 11111110   -1反码
	//11111111 11111111 11111111 11111111   -1补码
	//11111111 11111111 11111111 11111100  对补码左移2位,右边补2个0

	//11111111 11111111 11111111 11111011 反码,对上面补码-1
	//10000000 00000000 00000000 00000100 原码,对反码符号位不变,其他位按位取反
	printf("%d\n", i);
	return 0;
}

输出

-4

2.2 右移运算符 >>

语法:数字 >> n
对数字的补码右移n位,即右边抛弃,左边填充
根据填充规则分为两种:逻辑移位与算数移位
逻辑移位:左边用0填充
算数移位:左边用该数字符号位填充
标准规定:无符号类型的所有移位操作都是逻辑移位。对于有符号类型采用逻辑移位还是算数移位由编译器决定,大部分编译器采用算数移位,下面的演示环境采用的是算数移位。

#include <stdio.h>
int main() {
	int i = -1 >> 2;
	//10000000 00000000 00000000 00000001   -1原码
	//11111111 11111111 11111111 11111110   -1反码
	//11111111 11111111 11111111 11111111   -1补码
	//11111111 11111111 11111111 11111111  对补码右移动2位,左边全部补符号位1

	//计算后结果还是-1的补码,所以还原成原码不再写
	printf("%d\n", i);
	return 0;
}

输出

-1
#include <stdio.h>
int main() {
	int i =10 >> 2;
	//00000000 00000000 00000000 00001010   10原码
	//00000000 00000000 00000000 00001010   10反码
	//00000000 00000000 00000000 00001010   10补码
	//00000000 00000000 00000000 00000010  对补码右移动2位,左边全部补符号位0
	printf("%d\n", i);
	return 0;
}

输出

2

对于移位运算符,不要移动负数位,这个是C语言标准未定义的
如 int i = 10 >> -1 ;

三、位运算符

位运算符有:按位与 & 按位或 | 按位异或 ^ 三种

3.1 按位与 &

语法: num1 & num2
将两个数的补码计算出来,两个数对应的二进位都为1时,结果为1,否则为0

#include <stdio.h>
int main() {
	int i = 10 & -3;
	//00000000 00000000 00000000 00001010   10 的原码、反码、补码

	//10000000 00000000 00000000 00000011    -3 的原码
	//11111111 11111111 11111111 11111100    -3 的反码
	//11111111 11111111 11111111 11111101  -3 的补码
	 
	//00000000 00000000 00000000 00001010  10补码
	//11111111 11111111 11111111 11111101  -3 补码
	//00000000 00000000 00000000 00001000  对应二进制位都为1,结果为1,否则为0 
	printf("%d\n", i);
	return 0;
}

输出

8

3.2 按位或 |

语法: num1 | num2
将两个数的补码计算出来,两个数对应的二进位至少有1个为1时,结果为1,否则为0

#include <stdio.h>
int main() {
	int i = -4 | -3;
	//10000000 00000000 00000000 00000100   -4 的原码
	//11111111 11111111 11111111 11111011   -4 的反码
	//11111111 11111111 11111111 11111100   -4 的补码
	
	//10000000 00000000 00000000 00000011    -3 的原码
	//11111111 11111111 11111111 11111100    -3 的反码
	//11111111 11111111 11111111 11111101  -3 的补码
	 
	//11111111 11111111 11111111 11111100   -4补码
	//11111111 11111111 11111111 11111101   -3 补码
	//11111111 11111111 11111111 11111101  对应二进制位至少1个为1时,结果为1,否则为0 (此结果为补码)
	//11111111 11111111 11111111 11111100  反码,补码-1
	//10000000 00000000 00000000 00000011  原码,反码符号位不变,其他位按位取反
	printf("%d\n", i);
	return 0;
}

输出

-3

3.3 按位异或 ^

语法: num1 ^ num2
将两个数的补码计算出来,两个数对应的二进位相同时,结果为0,否则为1

#include <stdio.h>
int main() {
	int i = -4 ^ -3;
	//10000000 00000000 00000000 00000100   -4 的原码
	//11111111 11111111 11111111 11111011   -4 的反码
	//11111111 11111111 11111111 11111100   -4 的补码
	
	//10000000 00000000 00000000 00000011    -3 的原码
	//11111111 11111111 11111111 11111100    -3 的反码
	//11111111 11111111 11111111 11111101  -3 的补码
	 
	//11111111 11111111 11111111 11111100   -4补码
	//11111111 11111111 11111111 11111101   -3 补码
	//00000000 00000000 00000000 00000001  对应二进制位相同时,结果为0,否则为1 

	printf("%d\n", i);
	return 0;
}

输出

1

3.4 经典笔试题

题目:有两个整数类型变量a、b,不创建临时变量交换a与b的值

方法一

#include <stdio.h>
//当两个数相加和大于int类型时,存在溢出,此方法就不能使用
int main() { 
	int a = 10;
	int b = 20;
	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;
}

输出

交换前 a = 10 b = 20
交换后 a = 20 b = 10

方法二

#include <stdio.h>
int main() { //此方法只适用两个整数之间交换
	int a = 10;
	int b = 20;
	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;
}

输出

交换前 a = 10 b = 20
交换前 a = 20 b = 10

四、赋值运算符 =

将赋值运算符右侧的值赋给左侧的变量

#include <stdio.h》
int main() {
	int a = 20;
	a = 30; //使用赋值运算符将30赋给变量i
	int x = 1;
	int y;
	int z;
	z = y = x+1; //连续赋值 等同于 y = x+1; z=y;
	return 0;
}

复合赋值运算符: +=  -=  *=  /=  %=  >>=  <<=  &=  |=  ^=

等同于将复合赋值运算符左侧的变量与右侧的值通过运算符计算得到的结果赋值给左侧变量

#include <stdio.h>
int main(){
	int i = 10;
	i += 30 ;  // 等同于 i = i + 30;
	printf("%d\n",i);
	return 0;
}

输出

40

五、单目运算符

5.1 逻辑非运算符 !

在c语言中,0为假,非0为真。 逻辑非运算符逆转逻辑状态,
!真 -> 假   !假 ->真

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

输出

!i = 0
!j = 1
#include <stdio.h>
int main() {
	int i = 0;
	if (!i)  //当i为假时候输出哈哈哈
		printf("哈哈哈\n");
	return 0;
}

输出

哈哈哈

5.2 取地址运算符 & 与 间接寻址运算符 *

&变量名 : 取出变量在内存的地址   * 指针变量 :访问指针变量存储的地址所对应内存空间

#include <stdio.h>
int main() {
	int i = 10;
	int* p = &i;//取出i在内存中地址并存储在指针变量p中,这里 * 代表指针类型
	*p = 20;  //通过指针p间接访问变量i的内存空间,并修改i的值为20,这里* 代表间接寻址访问,即找到指针存储的地址对应的空间
	printf("i = %d\n", i);
	return 0;
}

输出

20

5.3 sizeof 运算符

sizeof是运算符而不是一个函数,求变量(类型)所占内存空间大小,单位为字节

#include <stdio.h>
int main() {
	int i = 10;
	printf("i所占空间大小为:%d\n", sizeof(i));
	printf("int类型所占空间大小为:%d\n", sizeof(int));
	printf("i所占空间大小为:%d\n", sizeof i); //这里 sizeof 求i的大小没有使用(),可以说明sizeof不是一个函数
	return 0;
}

输出

i所占空间大小为:4
int类型所占空间大小为:4
i所占空间大小为:4

5.4 取反运算符 ~

取反运算符 : 对一个数的二进制位(补码)取反 。 1变0,0变1

#include <stdio.h>
int main() {
	int i = ~10;
	//00000000 00000000 00000000 00001010  10的原码、反码、补码
	//11111111 11111111 11111111 11110101  按位取反后的补码
	//11111111 11111111 11111111 11110100  反码
	//10000000 00000000 00000000 00001011  原码
	printf("%d\n", i);
	return 0;
}

输出

-11

5.5 自增运算符 ++ 自减运算符- -

自增运算符分为前置++与后置++两种
前置++ 即先自增,后使用
后置++ 即先使用,后自增

#include <stdio.h>
int main() {
	int i = 10;
	int j = ++i; //i先自增+1,此时i=11,将11赋值给j
	int x = 10;
	int y = x++; //先将x赋值给y,此时y=10,然后x自增+1
	printf("i = %d\n", i);
	printf("j = %d\n", j);
	printf("x = %d\n", x);
	printf("y = %d\n", y);
	return 0;
}

输出

i = 11
j = 11
x = 11
y = 10

自减运算符分为前置- -与后置- -两种
前置- - 即先自减,后使用
后置- - 即先使用,后自减

5.6 强制类型转换运算符 ( )

强制类型转换是把变量从一种类型转换为另一种数据类型
语法:(type_name) expression

#include <stdio.h>
int main() {
	int i = (int)3.14; //将3.14这个double类型强制转换为int类型,小数位会被丢弃
	printf("%d\n", i);
	return 0;
}

输出

3

六、关系运算符

关系运算符包括: > >= < <= != ==
注意: 赋值运算符是 = , 判断两数是否相等使用 ==

#include <stdio.h>
int main() {
	int i = 10;
	int j = 20;
	if (i == j)
		printf("相等\n");
	else
		printf("不相等\n");
	return 0;
}

输出

不相等

七、逻辑运算符

7.1 逻辑与运算符 &&

如果&&左右两边表达式都为真,则结果为真,否则为假。当左边表达式为假,右边表达式不会进行判断执行

#include <stdio.h>
int main() {
	int age = 15;
	if (age > 12 && age < 18) //只有age大于12且小于18时才会执行
	{
		printf("青少年\n");
	}
	return 0;
}

输出

青少年
#include <stdio.h>
int main() {
	int i = 0;
	int j = 1;
	int c = i++ && j++; //i++是后置++,所以&&左边表达式为假,则右边表达式不会执行
	printf("i = %d j = %d c = %d\n",i,j,c);

	return 0;
}

输出

i = 1 j = 1 c = 0

7.2 逻辑或运算符 ||

如果||左右两边表达式至少有一个为真,则结果为真,否则为假。当左边表达式为真,右边表达式不会进行判断执行

#include <stdio.h>
int main() {
	int weight = 80; 
	if(weight < 90 || weight > 130) //当weight小于90或者大于130则执行
	{
		printf("体重不健康\n");
	}
	return 0;
}

输出

体重不健康
#include <stdio.h>
int main() {
	int i = 1;
	int j = 2;
	int z = i++ || j++; //i是后置++,此时i为1,左侧表达式为真,则右边表达式不会执行
	printf("i = %d j = %d z = %d\n", i, j, z);
	return 0;
}

输出

i = 2 j = 2 z = 1

八、条件运算符(三目运算符)

语法: 条件 ? X : Y
当条件为真时,值为X,否则为Y

#include <stdio.h>
int main() {
	int x = 10;
	int y = 20;
	int max = x > y ? x : y;
	printf("x与y的较大值为:%d\n", max);
	return 0;
}

输出

x与y的较大值为:20

九、逗号运算符

逗号运算符:从左向右依次执行。整个表达式的结果是最后一个表达式的结果
语法: (exp1, exp2, exp3, …expN)

#include <stdio.h>
int main() {
	int i = 10;
	int x = (10, i++,30);//括号内多个表达式从左到右依次执行,但最终结果只跟最后一个表达式有关,即 x = 30
	printf("%d\n",i);
	printf("%d\n", x);
	return 0;
}

输出

11
30

十、下标引用运算符 [ ] 与 函数调用运算符 ( )

10.1 下标引用运算符 [ ]

需要引用数组某个元素时: 数组名[下标]
数组下标从0开始,所以数组最后一个元素下标为数组元素个数-1
下标引用运算符 [ ] 有两个操作数,一个是数组名,一个是下标

#include <stdio.h>
int main() {
    int arr[5] = { 1,2,3,4,5 };
    printf("%d\n", arr[3]); //通过下标引用运算符引用arr数组的第4个元素
    printf("%d\n", 3[arr]); // [ ]是运算符,所以操作数可以交换位置,类似 a + b  等同于 b + a
    return 0;
}

输出

4
4

10.2 函数调用运算符 ( )

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

#include <stdio.h>
void print1() {
    printf("哈哈哈\n");
}

void print2(char* p) {
    printf("%s\n",p);
}
int main() {
   
    print1(); //使用函数调用运算符,有1个参数print1
    print2("hello");//使用函数调用运算符,有2个参数print1、"hello“
    return 0;
}

输出

哈哈哈
hello

十一、引用结构体(联合体)成员运算符

引用结构体(联合体)成员运算符有两个,一个是点运算符 .   一个是箭头运算符 ->
语法:
结构体变量.成员名
结构体指针变量->成员名

#include <stdio.h>

struct person {
    char name[10];
    int age;
    char sex[5];
};

void print1(struct person p) {
    printf("姓名:%s  年龄:%d  性别:%s\n", p.name, p.age, p.sex); //使用点运算符访问结构体变量的成员,运算符左侧为结构体变量
}

void print2(struct person* p) {
    printf("姓名:%s  年龄:%d  性别:%s\n", p->name, p->age, p->sex); //使用箭头运算符访问结构体变量的成员,运算符左侧为结构体指针变量
}
int main() {
    struct person p = { "康小龙",18,"男" };
    print1(p);
    print2(&p);
    return 0;
}

输出

姓名:康小龙  年龄:18  性别:男
姓名:康小龙  年龄:18  性别:男
  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值