C语言1. 算术操作符加统计二进制位1

  1. 整型:1/2–> 0
  2. 浮点数除法: 必须左右有1带小数点
  3. 移位操作符:
    整数二进制表示:原码、反码、补码;
    正整数三个码相同
    负的整数原码、反码、补码需要计算
    整型4字节:32位
    7表示为:
    0*(29)+111
    -7表示为:
    1+0*(28)+111 原码
    1 11…1111 + 0000反码 (原码符号位不变,其他位取反)
    1 11…1111+ 0001 补码(反码+1)
    整数在内存中存的是补码
    移位:
    左移:比如a=7: 末尾补0
    0…000000111 左移补0 变为: 0…001110 变大了加了2的多少次
    但是a不会变
    如果 a = -7
    补码:(左移后) 1111111111…110010
    直接减1取反 11111…110001 ->(取反)
    符号位不变1 000… 001110 -> 2+4+8=14
    最终结果 - 14
    右移:特别,分为两种, 取决于编译器:
    算术右移:右边丢弃,左边补原符号
    逻辑移位:右边丢弃,左边补0
    vs采用算术移位
    移位不能用负数
    最终结果:正数两种都不变,负数逻辑
总结:

左移:不论正数负数,结果都是乘2
右移:

  1. 位操作符

& 按二进制位与:
| 按二进制位或:
^ 按位异或: 异为1,同为0
程序里面做这些,都是以补码来做的

一道面试题:

  1. 不创建临时变量,交换两个整数值:
    思路:1. 简单:
    int a = 3; int b =5;
    a = a+b; // (需要a+b不溢出)
    b = a- b;
    2. 正规: 以a = 3、b = 5举例:
    a = a ^ b; 3 ^5
    b = a ^ b; 3 ^ 5 ^5 = 3
    a = a ^ b; 3 ^ 5 ^ 3 = 5
    如上,三次异或实现了交换
  2. 操作符
    单目:只操作一个操作数
    sizeof()其实是个单目运算符
    ++、–都是单目运算符
    强制类型转型也是单目运算符

两个数字比较的时候: 123 == 5: 是在比较值,而
string “abc” == “abcdef” 是在比地址
4. int a[10] = {0} 这样只是初始化了第一个
5. 弄懂stringcpy?,它为什么不直接赋值字符串呢??
*ps 是因为ps是指针,指向结构体,所以需要

练习:
  1. 求整数在内存中的二进制存储值:
    get_bit中1个数思路:
    让数字和1做&运算,如果为1则这个位为1,
    然后1再一次左移一次<<, 总共左移多次,
    这样让这个数字不断与自己不同位上的1做与,然而得到的结果除了第1位是1,但其它不是1,但是是2的某个次,因为它不在第一位做与。
int get_bit(int a)
{
	int b = 1;
	int count = 0;
	int f = a;
	while (f)
	{
		int t = 0;
		t = a & b;
		if (t != 0)
		{
			count++;
		}
		f /= 2;
		if (!f) { break; }
		b = b << 1;
	}
	return count;
}

int main()
{
	int a;
	int b;
	scanf("%d", &a);
	scanf("%d", &b);
	int res = a^b;
	// 看多少个位是1
	res = get_bit(res);
	printf("%d", res);
	return 0;
	 
}
  1. 打印整数二进制的奇数位和偶数位
    思路:
    放入数组存与结果,不是0就存入当前位置,
    注意:256是2的8次,但它是1+(0)*8
    因为二进制第一个位是2的0次
int convert_bit(int a, int res[33])
{
	int f = a;
	int b = 1;
	int i=1;
	while (f)
	{
		int t = a & b;
		if(t!=0)
		{
			res[i] = i;
		}
		b = b << 1;
		f /= 2;
		if (!f) { break; }
		i++;
	}
	return i;
}

// 打印整数二进制全部
int main()
{
	int a;
	scanf("%d", &a);
	int first;
	int res[33] = { 0 };
	first = convert_bit(a, res);
	printf("数字的二进制最高位为%d\n", first);
	// 因为二进制最后是2的0次,所以最高位是2的first-1次
	for (int i = first; i>=1;i--)
	{
		if (res[i] != 0)
		{
			printf("%d", 1);
		}
		else 
		{
			printf("%d", 0);
		}
	}
	return 0;
}

更牛的写法

统计二进制中1

以往思路:求10进制每一位,不断模10除10,求2进制每一位,不断模2除2得每一位。(负数不合适)
新思路:上面写法的改进

scanf(n);
int count = 0;
// 要求数向右移动32位,每次挪动都与1做&,统计1数量
for(int i=0;i<32;i++)
{
	if(((n>>i)&1)==1) {count++;}
}
return count;

n = n&(n-1); 每次让一个位归0,看需要几次变为0
1111 ->15
1110 ->14
1110 -> 14 做& n = 14
1101 -> 13
1100 -> 12 做& n = 12
1011 -> 11
1000 -> 8 做& n = 8
0111 -> 7 做& n = 7
0000 ->0 0
做了4次,所以有4个1 负数也适用

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

全局变量、静态变量在静态区,且静态变量不初始化会被初始化为0

int i;
int main()
{
i--;	// 全局变量不初始化默认为0 这里自减结果为-1
if(i>sizeof(i))  // sizeof返回 unsigned int 无符号整型
// 不同类型的数比较会转为较大的类型,即左边负数-1:1000转为理解成1000。。。会认为非常大,所以这个if成立

return 0;
}

问答:

  1. 为什么int类型的范围是:-2147483648~2147483647 【-2^31, 2^32-1】?

  答:int有32位,第1位是符号位,正数部分可以表示2^31中情况,然而其中有全0的情况,最大是2^32 -1。而负数有2^31次中情况,但是+0和-0原码不一样,补码也不一样,规定0作为0的原码、补码和反码,而-0的补码作为-(2^31)-1 = 2147483648,这个数字是规定,它没有原码,因为会溢出。所以-1的补码是边界值的形式补码。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值