C语言——操作符

  • 算术运算符

+   -   *   /   %

注:不可除0也不可模0

       两个整数相除得到的结果为整数。

  • 移位操作符

左移<<    右移>>

不可移动负数位

对于CPU来说,计算移位操作,效率远远高于计算除法操作

   移位操作是按照二进制进行移位:

左移一位相当于 *2,右移一位相当于 /2

#include <stdio.h>
#include <stdlib.h>

int main(){
	int num = 4;
	int num1= num << 1;
	int num2 = num >> 1;
	printf("num1=%d\n", num1);
	printf("num2=%d\n", num2);
	system("pause");
	return 0;
}

左移移位规则:

左边丢弃,右边补零

右移移位规则:

1.逻辑右移

   左边补零,右边丢弃

2.算术右移

   数字符号位填充左边,右边丢弃

  • 位操作符

&    |    ^

& 按位与:

全1为1,有0则0

注:逻辑与为&&

   按照二进制进行按位与:

#include <stdio.h>
#include <stdlib.h>

int main(){
	int num1= 2;  //10
	int num2 = 3; //11
	//按位与后得到 10,即2
	printf("%d & %d=%d\n", num1, num2,num1&num2);
	system("pause");
	return 0;
}

   通过按位与操作,把数字中的某些位截取出来:

#include <stdio.h>
#include <stdlib.h>

int main(){
	int num1= 33;  //0010 0001
	int num2 = 0xf; //按二进制表示为0000 1111
	int num3 = 0xf0; //1111 0000
	printf("%d 截取二进制最后一位的结果为:%d\n", num1, num1&num2);
	printf("%d 截取二进制前两位的结果转换为十进制为:%d\n", num1, num1&num3);
	system("pause");
	return 0;
}

| 按位或:

全0为0,有1则1

注:逻辑或为||

   按照二进制进行按位或:

#include <stdio.h>
#include <stdlib.h>

int main(){
	int num1= 4;  //100
	int num2 = 2; //010
	//按位或后得到110,即6
	printf("%d | %d = %d\n", num1, num2,num1|num2);
	system("pause");
	return 0;
}

^ 按位异或:

同0异1

   利用移位操作与位操作求取二进制数中1的个数:

#include <stdio.h>
#include <stdlib.h>

int main(){
	//利用移位操作与位操作求取二进制数中1的个数
	int num = 22;
	int count=0;
	for (int i = 0; i < 32; ++i){
		//循环一直测试num中的每一位
		//若num变量对应位为1,则按位与不为0
		if (num&(1 << i)){
			++count;
		}
	}
	printf("%d的二进制中有%d个1\n", num, count);
	system("pause");
	return 0;
}

  • 赋值操作符

=

可用于赋值,也可用于变量的初始化

复合赋值符:

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

  • 单目操作符

!              逻辑反操作

-                 负值

+                正值

&                取地址

sizeof         操作数类型长度(字节)

~                 对数的二进制按位取反

-- / ++

*                  间接访问操作符(解引用操作符)

(类型)     强制转换

   按位取反与逻辑取反:

逻辑取反得到的值是一个表示真假的值,按位取反得到的是二进制每一位的反

#include <stdio.h>
#include <stdlib.h>

int main(){
	unsigned int x = 0x0;
	int x1 = ~x;
	int x2 = !x;
	printf("%x按位取反:%x\n", x,x1);
	printf("%x逻辑取反:%x\n", x,x2);
	system("pause");
	return 0;
}

  若不取表达式的返回值,++x和x++没有区别:

#include <stdio.h>
#include <stdlib.h>

int main(){
	int x = 0;
	int x1=++x;
	printf("++x后的x为%d\n",x);
        x = 0;
	int x2=x++;
	printf("x++后的x为%d\n", x);
	system("pause");
	return 0;
}

  练习:

#include <stdio.h>
#include <stdlib.h>

int main(){
	int i = 1;
	int ret = (++i) + (++i) + (++i);
	printf("ret=%d\n", ret);
	system("pause");
	return 0;
}

注:不同的系统 / 编译器的到的结果可能不同,因为C语言标准中没有规定这种表达式的求值顺序,这是未定义行为。

  • 关系操作符

>   >=   <   <=   !=(不相等)   ==(相等)

注:== 和 = 的区别

返回值为真或假

  短路求值:

对于逻辑与来说,两个操作数任意一个为0,结果必然为0。若发现第一个操作数表达式的值已经为0,则不需要对第二个表达式进行求值。

对于逻辑或来说,两个操作数任意一个非0,结果必然为1。若发现第一个操作数表达式的值已经非0,则不需要对第二个表达式进行求值。

int main(){
	int i = 0, a = 0, b = 2, c = 4;
	i = a++ && ++b && c++; 
	//i = a++ || ++b || c++; 
	printf("a = %d\nb = %d\nc = %d\n\n", a, b, c); 
	system("pause");
	return 0;
}

  • 条件操作符

exp1 ? exp2 : exp3

若表达式1为真,则执行表达式2;否则,执行表达式3

  • 逗号表达式

exp1, exp2, exp3, …expN

用逗号隔开的多个表达式,从左向右依次执行。整个表达式的结果是最后一个表达式的结果。

  • 下标引用

[ ] 下标引用操作符

操作数:数组名 + 索引值

注:下标从0开始

  • 函数调用

( ) 函数调用操作符

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

  • 结构成员

.      结构体.成员名

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

. 成员访问操作符,直接给结构体变量使用

->成员访问操作符,给指向一个结构体变量的指针来使用

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct Student{
	char name[1024];
	int age;
};

int main(){
	struct Student student;
	struct Student*p= &student;
	strcpy(student.name, "张三");
	student.age = 20;
	printf("%s\n", p->name);
	printf("%d\n", p->age);
	system("pause");
	return 0;
}

  • 表达式求值

隐式类型转换: 

整型提升:

        CPU从内存中读取数据的时候,都是以4个字节为单位。只是读取一个字节,反而不如一次读4个字节更高效。如果是short或其他比int短的变量,都会有类似的提升过程。

#include <stdio.h>
#include <stdlib.h>

int main(){
	//字符类型的变量本质也是一个数字
	//char ->int 相加后再强制转换为char
	char a = 1;
	char b = 2;
	char c = a + b;
	printf("c=%d\n", c);
	system("pause");
	return 0;
}

   练习:

#include <stdio.h>
#include <stdlib.h>

int main(){
	unsigned char a=255;
	//本应为0111 1111
	//整型提升为0000 0000 0000 1111 1111
	//->0000 0000 0001 1111 1110
	//->0000 0000 0000 1111 1111
	//所以最终结果为1111 1111
	unsigned char b = (a<<1)>>1;
	printf("b=%x\n", b);
	system("pause");
	return 0;
}

算数转换:

       如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类型,否则操作就无法进行。

       如果某个操作数的类型在下表中排名较低,那么首先要转换为另外一个操作数的类型后执行运算。
 

long double
double
float
unsigned long int
long int
unsigned int
int

当作为函数参数传递时,char和short被转换位int,float转换位double

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值