05 操作符和表达式

5.1 操作符

位移操作符

左移情况比较简单,右边直接加0即可。但是右移操作符要注意了,分两种情况:

  • 逻辑位移,左边补0。

  • 算数位移,左边根据符号位来补。

右移到底是逻辑位移还是算数位移取决于编译器。(如果是无符号数,则可以放心右移)

一个计算数值中1的位的个数的例子

int count_one_bits (unsigned value)
{
int ones;
for (ones = 0; value != 0; value >>= 1) {
if ( value & 1 != 0) ones++;
}
return ones;
}

逗号操作符

逗号操作符将表达式分隔开。这些表达式自左向右逐个求值,整个逗号表达式的值就是最后一个表达式的值。

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

  • [] 下标引用操作符接受两个操作数:一个数组名和一个索引值。除优先级不同,下标引用操作符和间接访问表达式是等价的

    array[index]
    *(array + index)
  • () 函数调用运算符接受多个操作数。第一个操作数是函数名,后面的操作数就是函数的参数。

  • .->是结构成员操作符。

5.2 布尔值

C语言没有布尔型变量:0是假,非0 是真。

5.3 左值和右值

这两个术语由编译器设计者创造并沿用至今,尽管它们并不严格与c语言吻合。

一般来讲变量可以作为左值,而表达式不能。但是又两个例外,有些操作符的结果是左值,如间接访问和下标引用。

int a, *p;
p = a;
*p = 10;
a[b+10] = 123;

编程练习1

编写函数unsigned int reverse_bits(unsigned int value);。这个函数把二进制位从左到右反转,如value=25,在32位机器上,二进制位是00000000000000000000000000011001,转换后是10011000000000000000000000000000。所以函数的返回结果是2550136832。

#include<stdio.h>
unsigned int reverse_bits (unsigned int value)
{
unsigned int answer;
unsigned int i;
answer = 0;
/*
* 这样写回循环int的位数次,保证了与特定机器字长无关。value向左走,answer向右走,两者是mirror。
*/
for (i = 1; i != 0; i <<= 1) {
answer <<= 1;
if (value & 1) answer |= 1; /* 如果value最低位是1,则把answer的最低位也置1 */
value >>= 1;
}
return answer;
}
int test()
{
unsigned int value;
unsigned int answer;
value = 25;
answer = 2550136832;
if (reverse_bits(value) == 2550136832) return 1;
else return 0;
}
int main()
{
if (test()) printf("Success.\n");
else printf("Failed.\n");
}