C语言从入门到精通——初阶5 操作符

 69 操作符详解

算数操作符

+ - * / %

  1. 除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数
  2. 对于 / 操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除法
  3. % 操作符的两个操作数必须为整数。返回的是整除之后的余数

移位操作符(二进制位)

  • 不能移动负数位,例如10>>-1 //error

>>右移操作符

1.算数右移(基本上都是)

右边丢弃,左边补原符号位

2.逻辑右移

右边丢弃,左边补0

<<左移操作符

左边丢弃,右边补0

位操作符

&        按位(2进制位)与

|        按位或

^        按位异或形同为0,相异为1

(操作数必须为整数) 

//不创建临时变量,实现两个数的交换

//加减法
a=a+b;//缺陷:可能会溢出
b=a-b;
a=a-b;
  • 异或的结果和原来其中一个值异或能得到另外一个值
  • a^a=0; 0^a=a; 
int main()
{
	int a = 10;
	int b = 20;
	printf("before:a=%d b=%d\n", a, b);
//异或法
	a = a ^ b;
	b = a ^ b;
	a = a ^ b;
	printf("after:a=%d b=%d\n", a, b);
	return 0;
}

//求一个整数存储在内存中的二进制数中1的个数

	while (num)
	{
		if (num % 2 == 1)
			count++;
		num = num / 2;
	} 

方法2 :

for (i = 0; i < 32; i++)
{
	if(1==(num>>i)&i)
		count++:
}

赋值操作符

单目操作符

只有一个操作数

  •  ! 逻辑反操作
  • - 负值
  • + 正值
  • & 取地址
  • sizeof()操作数的类型长度,以字节为单位
  • ~ 按位取反(包括符号位)
  • -- ++ 前置  (先++ --再使用)
  • 后置 -- ++    (先使用再++ --)
  • * 间接访问操作符(解引用操作符)
  • (类型) 强制类型转换

sizeof(表达式):sizeof()里面的表达式不参与运算

 关系操作符

>         >=        <        <=        !=        ==

=赋值        == 判断相等

比较两个字符串相等时,不能使用==

逻辑操作符

&&         逻辑与         如果左边算出来是假,右边不会进行运算

||           逻辑或          如果左边算出来是真,右边不会进行运算

条件操作符

(三目操作符)

condition ? consequent : alternative

condition 表达式的计算结果必须为 true 或 false。 若 condition 的计算结果为 true,将计算 consequent,其结果成为运算结果。 若 condition 的计算结果为 false,将算 alternative,其结果成为运算结果。 只会计算 consequent 或 alternative

逗号表达式

逗号表达式:从左向右依次执行,整个表达式的结果是最后一个表达式的结果

下标引用、函数调用和结构成员

[ ] 下标引用操作符

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

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

访问一个结构的成员

.          结构体.成员名

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

//创建了一个自定义的类型
struct Book
{
	//结构体的成员(变量)
	char name[20];
	char id[20];
	int price;
};

int main()
{
	//结构体变量名.成员名
	struct Book b = {"C语言", "C20210509", 55};
	struct Book * pb = &b;

	//结构体指针->成员名
	printf("书名:%s\n", pb->name);
	printf("书号:%s\n", pb->id);
	printf("定价:%d\n", pb->price);

	printf("书名:%s\n", (*pb).name);
	printf("书号:%s\n", (*pb).id);
	printf("定价:%d\n", (*pb).price);

	printf("书名:%s\n", b.name);
	printf("书号:%s\n", b.id);
	printf("定价:%d\n", b.price);

	return 0;
}

74 表达式求值

隐式类型转换 

整型提升:在表达式计算时,各种整形首先要提升为int类型,如果int类型不足以表示则要提升为unsigned int类型;然后执行表达式的运算。

C语言标准中仅规定了:

char的长度 ≤ short int的长度 ≤ int的长度

这意味着short int与int的长度相等的可能。这种情形下,unsigned short就无法提升为int表示,只能提升为unsigned int。

整形提升是按照变量的符号位来提升的。无符号整形提升,高位补0。 

int main()
{
	//发现a和b都是char类型的,都没有达到一个int的大小
	//这里就会发生整形提升
	char a = 3;
	//00000000000000000000000000000011
	//00000011 -char a
	char b = 127;
	//00000000000000000000000001111111
	//01111111 - char b

	char c = a + b;
	//00000000000000000000000000000011 a整形提升后
	//00000000000000000000000001111111 b整形提升后
	//00000000000000000000000010000010 c
	
	//10000010 - c只能放入8位
	//打印的是%d,发生整形提升,高位是1,补1
	//11111111111111111111111110000010 - 补码 提升后
	//11111111111111111111111110000001 - 反码
	//10000000000000000000000001111110 - 原码
	//-126

	printf("%d\n", c); //-126

	return 0;
}
int main()
{
	char a = 0xb6;
	short b = 0xb600;
	int c = 0xb6000000;

	if (a == 0xb6)
		printf("a");
	if (b == 0xb600)
		printf("b");
	if (c == 0xb6000000)
		printf("c");

	return 0;
}

 结果:只能打印出c

0xb6——1011 0110

编译器把char定义为signed char(C语言标准没有规定char类型是有符号还是无符号);表达式a==0xb6被整型提升,其中char类型的a提升为int类型并为一个负值,因此这个表达式的结果为false;表达式b==0xb600被整型提升,其中short类型的b提升为int类型并为一个负值,因此这个表达式的结果为false;表达式c == 0xb6000000没有做整型提升,==运算符的两段都是int类型的负值,其结果为true。

int main()
{
	char c = 1;
	printf("%u\n", sizeof(c));//1  char
	printf("%u\n", sizeof(+c));//4 unsigned int
	printf("%u\n", sizeof(-c));//4 unsigned int
	printf("%u\n", sizeof(!c));//4 gcc 编译为 4  unsigned int

	return 0;
}

c只要参与表达式运算,就会发生整形提升 

算术转换

94 算数转换作业讲解

//计算参数n的二进制补码中有几个1

//存在一定的问题:只能求正数
int NumberOf1(int n)
{
	int count = 0;
	while (n)
	{
		if (n % 2 == 1)
		{
			count++;
		}
		n /= 2;
	}
	return count;
}

int NumberOf1(int n)
{
	int count = 0;
	int i = 0;
	for (i = 0; i < 32; i++)
	{
		if (((n >> i) & 1) == 1)
		{
			count++;
		}
	}
	return count;
}

每次n&(n-1) 都去掉二进制数中的一个1

int NumberOf1(int n)
{
	int count = 0;
	int i = 0;
	while (n)
	{
		n = n & (n - 1);
		count++;
	}
	return count;
}

//写一个代码判断一个数字是不是2的n次方
因为2的n次方的数字,其中只有一个1。只需判断下(k&(k-1) == 0),等于0就是2的n次方。

 //二进制不同位的个数

	for (i = 0; i < 32; i++)
	{
		if (((m >> i) & 1) != ((n >> i) & 1))
		{
			count++;
		}
	}

//另一种方法

	int ret = m ^ n;//相同为0,相异为1
	count = NumberOf1(ret);//统计下异或后的结果中有几个1,就说明m和n的二进制位中有几个不同
	printf("%d\n", count);

//打印整数二进制的奇数位和偶数位

	int i = 0;
	//打印偶数位
	for (i = 31; i >= 1; i -= 2)
	{
		printf("%d ", (n >> i) & 1);
	}
	printf("\n");
	//打印奇数位
	for (i = 30; i >= 0; i -= 2)
	{
		printf("%d ", (n >> i) & 1);
	}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值