三目运算符是条件运算符。 三目运算符通过判断问号之前的表达式的真假来确定整体表达式的值。 条件运算符优先级高于赋值运算符,即可以通过max=a>b?a:b的形式输出两个数中的最大值。
逗号表达式的整体值是最后一个表达式的值。 在归并排序中有使用过,如下: for (i = low, j = mid + 1; i <= mid && j <= high;)此处不关心逗号表达式的整体值,只是对两个变量做初始化。 逗号运算符优先级最低。 逗号表达式不限制逗号的数量。
自增自减运算符和取值运算符 后++或后--的计算时,先去掉自增自减运算符,将其他表达式计算完成后,再执行自增自减运算。 如j=i++>-1,先比较i>-1,再将比较后的结果赋给j,最后执行i++。 ::: tip 后置++,就是先使用(先赋值),再++。 前置++,就是先++,再使用(再赋值)。 ::: ::: warning 后置- -和前置- -直接按照运算符优先级计算。 只有比后置++或后置- -优先级更高的操作符,如(),[],才可以和后置++、- -作为一个整体。 ::: 如下: int a[3]={3,4,5}; int* p=a; int j; j=p++; //p取到数组首元素地址,p得到首元素3,先计算j=p得j=3,再p++,指向数组第二个元素 j=p[0]++; //p[0]取到数组第二个元素4,再p[0]++,即4+1,得到5 *上述代码中,和++优先级相同,所以分开计算;[]优先级高于++,所以可以把p和[0]放在一起++。* 即代码运行结束后,j=4,*p=5。
优先级用来标识运算符在表达式中的运算顺序,在求解表达式的值的时候,总是先按运算符的优先次序由高到低进行操作。但是当一个运算对象两侧的运算符的优先级相同时,则按运算符的结合性来确定表达式的运算顺序。 结合性是指同一优先级的运算符在表达式中操作的组织方向,即:当一个运算对象两侧的运算符的优先级别相同时,运算对象与运算符的结合顺序。第二优先级的运算符结合方向是从右向左,较易出错。
位运算符
位运算符<<、>>、、|、^、&含义分别是左移、右移、按位取反、按位或、按位异或、按位与。
::: warning
位运算符的操作数是二进制数。位运算符只能对整型数据进行操作。
:::
移位的效率高于乘法和除法。
::: tip
左移(<<):高位丢弃,低位补0,相当于×2。
右移(>>):低位丢弃,正数高位补0,(无符号数认为是正数),负数高位补1,相当于÷2。
:::
无符号数(unsigned):所有二进制位都是数值位,没有符号位。无符号数只能是正数或0,不能是负值。
::: tip
有符号数第一位是符号位,剩下的数值位在前面补一个0,然后计算值。
不写unsigned的二进制的第一位就会被认为是符号位,0为正,1为负。
负数右移对偶数来说是除以2,对奇数来说先减1再除以2。
:::
上述C语言的左移和右移是算术左移和算术右移,逻辑左移和上述算术左移没有区别(高位丢弃低位补0),逻辑右移高位无论正负数一律补0。
按位异或(^):相同数字异或结果为0,不同数字异或结果为1。任何数字和0异或的结果都是其本身。
按位取反():1变为0,0变为1。
按位与(&)、按位或(|):两个数字的每一位进行与和或的操作。
::: warning 二进制数左移右移不改变数字本身。 ::: 如十六进制数0x8011,二进制为1000 0000 0001 0001,首位被认为是符号位,1表示负数,右移前面加1,变为11000 0000 0001 000。 如果0x8011是无符号数,二进制为1000 0000 0001 0001,没有符号位,右移前面加0,变为0100 0000 0000 1000。 ::: tip 在计算数值时,有符号数的数值位前面默认补0再计算,无符号数所有位置都是数值位参与计算,如果数值是正数,有符号数和无符号数计算结果相同;如果是负数,有符号数和无符号数相差32768,即相差无符号数的首位1,二进制数1000 0000 0000 0000。 ::: 可以通过计算器验证。 异或的使用:当一个数组中有有一个数字只出现一次,其他数字出现两次的情况。result初始值必须为0。
int main()
{
int i = 0;
int arr[5] = { 5,6,7,6,5 };
int result = 0; //初始时使用0和数组元素进行异或
for (i; i < 5; i++)
{
result^= arr[i];
}
printf("%d", result);
return 0;
}