这是上一篇文章留下的问题,这里为大家作答:
- //统计二进制中1的个数
- int statistics(int a)
- {
- int count = 0;
- for (int i = 0; i < 32; i++)
- {
- if (a & 1)
- {
- count++;
- }
- a = a >> 1;
- }
- //while (a)
- //{
- // a = a & (a - 1);//每次都会消去一个1
- // count++;
- //}
- return count;
- }
- int main()
- {
- int a = 0;
- scanf("%d", &a);
- int num = statistics(a);
- printf("%d\n", num);
- }
未被注释的部分就是运用位操作符实现的代码,注释的部分也是一种方法,但是这种方法很少被想到。
赋值操作符就是 = 可以为变量赋上一个自己满意的值:
- int num;
- num = 10;//这就是赋值
并且赋值可以连续使用:
- int a;
- int b;
- int c;
- a = b = c+1;
但是同样的意思下分开写不是更让人知道且易于调试:
- a = b;
- b = c+1;
- +=
-
- -=
-
- *=
-
- /=
-
- %=
-
- >>=
-
- <<=
-
- &=
-
- |=
-
- ^=
这些都是复合赋值操作符
- ! 逻辑反操作
-
- - 负值
-
- + 正值
-
- & 取地址
-
- sizeof 操作数的类型长度(以字节单位)
-
-
- ~ 对一个数的二进制按位取反(~0 就是 -1)
-
- -- 前置或后置--
-
- ++ 前置或后置++
-
- * 解引用操作符
-
- (类型) 强制类型转换
-
来看一段代码:这里的1 2 3 4 会输出什么?
- void teer1(int arr[])
- {
- printf("3:%d\n", sizeof(arr));
- }
- void teer2(char arr[])
- {
- printf("4:%d\n", sizeof(arr));
- }
-
- int main()
- {
- int arr1[10] = { 0 };
- char ch[10] = { 0 };
- printf("1:%d\n", sizeof(arr1));
- printf("2:%d\n", sizeof(ch));
- teer1(arr1);
- teer2(ch);
-
- }

我们说过数组名其实是首元素的地址,但是sizeof是一个特例,sizeof计算的是整个数组,但是函数传参传的是数组名也就是地址,地址的大小都是一样的。
- >
-
- >=
-
- <
-
- <=
-
- !=
-
- ==
注意:==才是比较 ,= 是赋值
- &&
-
- ||
- #include
-
- int main()
- {
- int i = 0, a = 0, b = 2, c = 3, d = 4;
- i = a++ && ++b && d++;//逻辑与&& 如果前面已经知道为假了,后面就都不会计算了。
- printf("a=%d,b=%d,c=%d,d=%d\n", a, b, c, d);
-
- }

- #include
-
- int main()
- {
- int i = 0, a = 0, b = 2, c = 3, d = 4;
- i = a++ || ++b || d++;//逻辑或|| 如果知道前面有一个为真了,后面也不会计算了。
- printf("a=%d,b=%d,c=%d,d=%d\n", a, b, c, d);
-
- }
条件操作符exp1 ? exp2 : exp3;
条件操作符,最常用的方式就是找两个数的最大数:
- int a = 5;
-
- int b = 6;
-
- int i = 0;
-
- i = a > b ? a : b;
exp1,exp2,exp3,.......
逗号表达式就是用逗号把多个表达式隔开,是从左向右依次执行,整个表达式的结果是最后一个表达式的结果。
- int a = 1;
-
- int b = 2;
-
- int c = (a>b,a=b+10,b=a+1);
上述代码中,c 是多少? 答案是13。
C语言中整数运算是以整形类型精度进行的,为了这个精度,表达式中的字符和短整型在使用前会被转换为普通整形,这种转换被叫做整形提升
- char a,b,c;
-
- .......
-
- a = b + c;
b 和 c 就会被提升为普通整形,然后在执行加法,加法之后结果会被截断,然后再存储在a 中。
整形提升是按照变量的数据类型的符号位来提升。(符号位就是二进制最左边的数字,1即负,0即正)
- char c1 = -1;
-
- 变量从c1的二进制补码是8个比特位
-
- 11111111
-
- 因为char是有符号的char
- 所以高位补充符号位,即1:
-
- 11111111111111111111111111111111
-
-
-
- char c2 = 1;
-
- 变量c2的二进制补码也是8个比特位
-
- 00000001
-
- 因为是有符号的char
- 所以高位补充符号位,即0:
-
- 00000000000000000000000000000001
-
-
如果某个操作符的各个操作数属于不同的类型,那么必须进行操作数的类型转换,否则无法进行操作,下面是寻常算术转换:
- long double
-
- double
-
- float
-
- unsigned long int
-
- long int
-
- unsigned int
-
- int
如果在这个排行中排名低,那么要转换成高的才可以进行运算。
算术转换要合理,要不然有潜在问题
复杂表达式的求值有三个影响的因素:
1.操作符的优先级
2.操作符的结合性
3.是否控制求值顺序
注意:函数的调用先后顺序无法通过操作符的优先级确定,类如下面代码就是有问题的:
- int fun()
- {
- static int count = 1;
- return ++count;
- }
-
- int main()
- {
- int answer;
- answer = fun() - fun() * fun();
- printf("%d\n", answer);
- }
总结:两个相邻的操作符先执行哪个,取决于优先级,如果相同,取决于他们的结合性(可以在网上查)。如果我们的表达式无法通过操作符的属性确定唯一的计算路径,那么就是有问题的。