【笔记】操作符总结

1.算数操作符

+    -   *   /   %
  1. 除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数。

  2. 对于 / 操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除法。

  3. % 操作符的两个操作数必须为整数。返回的是整除之后的余数。

2.位移操作符

<< 左移操作符
>> 右移操作符
    
注:移位操作符的操作数只能是整数。

2.1左移操作符

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

2.2右移操作符

移位规则:

首先右移运算分两种:

  1. 逻辑移位 左边用0填充,右边丢弃
  2. 算术移位 左边用原该值的符号位填充,右边丢弃

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

例如:

int num = 10;
num>>-1;//error

3.位操作符

  • & – 按位与
  • | – 按位或
  • ^ – 按位异或 —相同为0;相异为1
    注:他们的操作数必须是整数。
//按位与
int main()
{
	int a = 3;
	int b = -5;
	int c = a & b;
	//00000000000000000000000000000011 - 3的补码
	//10000000000000000000000000000101
	//11111111111111111111111111111010
	//11111111111111111111111111111011 - -5的补码
	//00000000000000000000000000000011 - 3的补码
	//00000000000000000000000000000011 - 3的补码  两个里面只要有0 就为0;两个都为1就为1;
	//
	//%d 意味着打印一个有符号的整数
	//
	printf("c=%d\n", c);

	return 0;
}

//按位或
int main()
{
	int a = 3;
	int b = -5;
	int c = a | b;
	//00000000000000000000000000000011 - 3的补码
	//10000000000000000000000000000101
	//11111111111111111111111111111010
	//11111111111111111111111111111011 - -5的补码
	//00000000000000000000000000000011 - 3的补码
	//11111111111111111111111111111011 - 补码   两个里面一个为1就为1	;两个为0就为0;
	//11111111111111111111111111111010   减一为反码
	//10000000000000000000000000000101   符号位不变其他位取反为原码
	//-5
	//%d 意味着打印一个有符号的整数
	//
	printf("c=%d\n", c);

	return 0;
}


位操作符的使用

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

3^3 = 0 -> a^a=0
011
011
000
0^5=5 -> 0^a = a
000
101
101

3^3^5 = 5
3^5^3 = 5
异或操作符支持交换律
011
101
110
011
101


//创建了第三个变量
int main()
{
	int a = 3;
	int b = 5;

	printf("交换前:a=%d b=%d\n", a, b);
	a = a ^ b;//a=3^5
	b = a ^ b;//3^5^5 --> b=3
	a = a ^ b;//3^5^3 --> a=5

	printf("交换后:a=%d b=%d\n", a, b);

	return 0;
}

 //会有溢出问题
int main()
{
	int a = 3;
	int b = 5;
  //这种方法会有溢出的问题
	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;
}

int main()
{
	int a = 3;
	int b = 5;
	int c = 0;//空瓶

	printf("交换前:a=%d b=%d\n", a, b);
	c = a;
	a = b;
	b = c;
	printf("交换后:a=%d b=%d\n", a, b);

	return 0;
}

4.关系操作符

int main()
{
	if (3 == 5)
	{
	}
	//err
	if ("abc" == "abcdef")//这样写是在比较2个字符串的首字符的地址
	{

	}
  //两个字符串比较相等应该使用strcmp
	return 0;
}

5.逻辑运算符

  • && 左边为假,右边就不计算了
  • || 左边为真,右边就不计算了
#include <stdio.h>
int main()
{
	int i = 0, a = 0, b = 2, c = 3, d = 4;
	//i = a++ && ++b && d++;

	i = a++ || ++b || d++;

	printf("a = %d\nb = %d\nc = %d\nd = %d\n", a, b, c, d);

	return 0;
}

6.条件操作符(三目操作符)

exp1 ? exp2 : exp3;
//如果表达式1为真,则计算表达式2的结果
//如果表达式1为假,则计算表达式3的结果
//eg:
int main()
{
	int a = 3;
	int b = 0;
	
	int max = (a > b ? a : b);

	if (a > 5)
		b = 3;
	else
		b = -3;
	
	(a > 5) ? (b = 3) : (b = -3);//以上代码使用条件运算符写方法1

	b = (a > 5 ? 3 : -3);//方法2

	return 0;
}

7.逗号表达式

exp1, exp2, exp3, …expN
  • 逗号表达式,就是用逗号隔开的多个表达式。 逗号表达式,从左向右依次执行。
  • 整个表达式的结果是最后一个表达式的结果。
//代码1
int a = 1;
int b = 2;
int c = (a>b, a=b+10, a, b=a+1);//逗号表达式
c是多少?
//代码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)
{
         //业务处理
}

8.下标引用,函数调用和结构体成员

8.1[ ] 下标引用操作符

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

int main()
{
	int arr[10] = { 0 };
	//
	//arr[7] --> *(arr+7) --> *(7+arr) --> 7[arr]
	// 
	//arr是数组首元素的地址
	//arr+7就是跳过7个元素,指向了第8个元素
	//*(arr+7) 就是第8个元素
	//
	arr[7] = 8;
	7[arr] = 9;


	//[] arr 7
	//3 + 5;
	//5 + 3;
	return 0;
}

8.2( ) 函数调用操作符

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

//函数定义
int Add(int x, int y)
{
	return x + y;
}

int main()
{
	int a = 10;
	int b = 20;
	//函数调用
	int c = Add(a, b);//() 就是函数调用操作符,操作数:Add,a,b
	//
	//sizeof a;

	return 0;
}

8.3访问一个结构的成员

#include <string.h>

struct Stu
{
	char name[20];
	int age;
	double score;
};

void set_stu(struct Stu* ps)
{
	//strcpy((*ps).name, "zhangsan");
	//(*ps).age = 20;
	//(*ps).score = 100.0;
	
	//(*ps).age  等价于  ps->age
	
	strcpy(ps->name, "zhangsan");//结构体指针->成员
	ps->age = 20;
	ps->score = 100.0;
}

//void print_stu(struct Stu ss)
//{
//	printf("%s %d %lf\n", ss.name, ss.age, ss.score);//结构体对象.成员
//}

void print_stu(struct Stu* ps)
{
	printf("%s %d %lf\n", ps->name, ps->age, ps->score);
}

int main()
{
	struct Stu s = {0};
	set_stu(&s);//数组传的是地址
	print_stu(&s);

	return 0;
}

9.隐式类型转换

  • C的整型算术运算总是至少以缺省(缺省=默认)整型类型的精度来进行的。
  • 为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升。

为什么需要整形提升?

C的整形算术运算总是至少以缺省类型的精度来进行的,为了获得这个精度,表达式中的字符型和短整型操作数在使用之前被转换 为普通类型,这种转换称为整形提升. 比如: char a,b,c; a = b + c; b和c的值被提升为普通整形,然后在执行加法运算.

int main()
{
	char a = 5;
	//00000000000000000000000000000101
	//00000101 - a(char类型1个字节8个比特位)
	char b = 126;
	//00000000000000000000000001111110
	//01111110 - b(char类型1个字节8个比特位)

	char c = a + b;
	//00000000000000000000000000000101 - a
	//00000000000000000000000001111110 - b
	//00000000000000000000000010000011
	//10000011 - c(char类型1个字节8个比特位)
	//11111111111111111111111110000011 - 补码(整型提升后)
	//11111111111111111111111110000010 - 反码
	//10000000000000000000000001111101 - 原码
	//
	printf("%d\n", c);//-125

	return 0;
}

1.无符号整形提升,高位补0

2.有符号的整形提升,高位补其符号位

  1. 负数的整形提升
    char a = -1;
    a为负数,其补码为1111 1111,占8个比特位
    (vs 2013 默认为有符号的)char为有符号的char
    整形提升时高位补充符号位 1
    提升结果为:1111 1111 1111 1111 1111 1111 1111 1111
  2. 正数的整形提升
    char b = 1;
    b为正数,其补码为0000 0001,占8个比特位
    char为有符号char
    整形提升高位补充符号位 0
    提升结果为:0000 0000 0000 0000 0000 0000 0000 0001
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值