3.程序题:求一个整数的二进制序列中有多少个1
方法1:
使用计数器变量count,让每一位二进制位分别移到最后面,与上1->如果相与之和的结果为1,count++
如何让每一位二进制位分别移到最后面?
-> 按位右移把每一个位都得到进行判断
->int :4个字节,->32位->右移32次
用循环:右移0位(此时为二进制序列最后一位)开始,到右移31位
此种写法对于负数也可以
int main() { int count = 0; int i = 0; int n = 0; scanf("%d",&n); for(i = 0;i < 32; i++) { //写法1: // n>>i :右移i位 if( ((n>>i) & 1 )== 1) { count++; } //写法2 int b = 0; b = n &1; if(b == 1) { count++; } n = n>>1; //n先与1进行判读, 再右移一位 } printf("%d的二进制序列中,1的个数为:%d\n",n,count); return 0; } 复制代码
方法2:n &(n-1)
每进行一次可以去掉n中二进制序列中最后一位比特位
此种方法对于负数也适用
int count_bit(int n ) { int count = 0; while(n) { count ++; n = n&(n-1); //将n&(n -1)得到的值赋给n } return count; } int main() { int n = 0; scanf("%d",&n); int count = count_bit(n); printf("%d的二进制序列中共有%d个1\n",n,count); return 0; } 复制代码
4.计算一个数是否为2的次方数
方法:n &(n-1)
n&(n-1):去掉二进制序列中最后一个1 对于2的次方数,二进制序列中只有一个1 如4: 0000 0100 8: 0000 1000 如果n&(n-1)为0,那么就是2的次方数 复制代码
//如果是2的次方数就返回1,不是返回0 int is_power_2(int n) { // if(n &(n-1) == 0) //ERR写法 原因:==的优先级比&高,有可能先算(n-1)==0 ,所以应该前面的东西括起来和0比较 if((n & (n-1)) == 0) { //n就是2的次方数 return 1; } else { return 0; } } int main() { int n = 0; printf("输入操作数:\n"); scanf("%d",&n); int ret = is_power_2(n); ////如果n是2的次方数 ret=1,不是,ret = 0 if(ret) { printf("%d是2的次方数\n",n); } else { printf("%d不是是2的次方数\n",n); } return 0; } 复制代码
5.交换变量a,b的值
01:采用临时变量
int main() { int a = 0; int b =0; scanf("%d %d",&a,&b); printf("before:a = %d b = %d\n",a,b); //交换 int tmp = a; a = b; b = tmp; printf("before:a = %d b = %d\n",a,b); return 0; } 复制代码
//写成函数的形式->传址 //若传值,形参是实参的一份临时拷贝,对形参的改变不影响实参 void Swap(int* pa,int* pb) { int tmp = *pa; *pa = *pb; *pb = tmp; } int main() { int a = 0; int b =0; scanf("%d %d",&a,&b); printf("before:a = %d b = %d\n",a,b); Swap(&a,&b); //Swap(a,b); ---err printf("before:a = %d b = %d\n",a,b); return 0; } 复制代码
02:不采用临时变量
方法1:
int main() { int a = 0; int b = 0; scanf("%d %d",&a,&b); printf("before:a = %d b = %d\n",a,b); a = a + b; //a存放a+b的和 b = a - b; //和 - b就是原来的a a = a - b; //现在b存放的是a的值,和 - a就是原来的b printf("after:a = %d b = %d\n",a,b); return 0; } 复制代码
缺陷:当a,b的值过大时,c = a+ b 可能会溢出
方法2 -- 不采用临时变量
a^b -得到密码 密码^b -> 原来的a 密码^a ->原来的b 异或:a^a ->0 0^a ->a 所以a^a^b 结果是:b a^b^a 结果是 b 结论:异或是支持交换律的 复制代码
//使用异或 int main() { int a = 0; int b = 0; scanf("%d %d",&a,&b); 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; } //记忆方法: 左边 a b a 右边:a^b 复制代码
缺点:但是代码可读性不高,同时该代码只适用于整形
= 赋值操作符
int main() { int a = 10; int x = 0; int y = 20; a = x = y+1; //把y+1的值赋给x, 再把x=y+1的值赋给a printf("%d\n",a);//21 printf("%d\n",x);//21 return 0; } 复制代码
& 取地址操作符
& :取出的是低地址 复制代码
int main() { int a = 10; int* p = &a; int b = *p; //对指针解引用就是指针指向的内容 // p存放的是a的地址,所以 *p 就是a *p = 20; //把p指向空间的值改成20 printf("%d\n",a); //20 return 0; } 复制代码
int a = 200; int c = b; //b为右值, 把 b指向空间的内容 赋给c b = 1000; //b为左值,使用的是b的空间 把1000放到b的空间里 复制代码
sizeof()操作符
sizeof()是计算类型或者变量所占内存空间的大小,单位是字节 。和内存中存放什么数据没有关系 注意:sizeof是操作符,不是函数 复制代码
如:
char arr[10] = "abc"; printf("%d\n",sizeof(arr)); //是10 不是3 //和内存存放的数据无关,计算的是数组的大小, 数组名单独放在sizeof内部,计算的是整个数组的大小 复制代码
证明sizeof()不是函数
int main() { int a = 10; int ret = sizeof(a); int ret2 = sizeof a; int ret3 = sizeof(int); // int ret4 = sizeof int; err printf("%d %d %d\n",ret,ret2,ret3); // 4 4 4 return 0; } 复制代码
不可以写成sizeof int 但是可以写成sizeof (int)
而sizeof a 和sizeof (a)都可以
由此可以证明 sizeof() 不是函数 因为函数一定要加括号调用 如Add(x,y);
sizeof对于变量:可以省略括号,但是对于变量类型不可以省略
sizeof()内部的表达式不参与真实运算
如:下例子, sizeof内部写的是赋值表达式也不会真实赋值
int main() { int a = 1; int ret = sizeof(a = a +1); //sizeof计算的是赋值之后的结果的类型,相当于sizeof(2) = 4 printf("%d %d\n",a,ret);// 1 4 return 0; } 复制代码
int a = 5; short s = 10; printf("%d\n",sizeof(s = a+2)); //2 printf("%d\n",s); //10 复制代码
a是int类型 4个字节,放到short变量s中, short:2个字节,会发生截断,只取a中低地址的两个字节 最后sizeof计算的是s的大小,s为short类型,所以大小为2