C-运算符,表达式

算术运算符

运算符 含义
+
-
*
/
% 取模(求余数)

ps:
整数除法会截断结果中的小数部分。(即只保留整数部分)
%运算符只能用于整型数据。
算术运算符采用从左到右结合规律。
 
 

关系运算符

运算符 含义
> 大于
>= 大于等于
< 小于等于
<= 小于等于
== 等于
!= 不等于

在关系表达式中,若关系为真则表达式的结果值为1,若为假,则结果值为0。
 
 

逻辑运算符

运算符 含义
&& AND(并且)
|| OR(或者)
! NOT(非)

在逻辑表达式中,如果运算结果为真,则结果值为1,若为假,则结果值为0。
(实际上就是将所连接的表达式的值进行布尔运算)
ps:
由&&和|| 连接的表达式按从左到右的顺序进行求值,一旦能够推断出结果值的真假后立即停止运算。(如:&&连接中有一假则结果为假,||连接中有一真则结果为真)
&&运算进行到遇到的第一个假值或最后(全为真)。
||运算进行到遇到的第一个真值或最后(全为假)。
练习
在不使用&&或||的情况下编写一个与下面for循环语句等价的循环语句。


for (i = 0; i < lim - 1 && (c=getchar()) != '\n' && c != EOF ; ++i)
    //循环体

解答1:

enum loop { NO, YES};
enum loop okloop = YES;

i = 0;
while (okloop == YES)
    if (i >= lim - 1)
        okloop = NO;
    else if ((c = getchar()) == '\n')
        okloop = NO;
    else if (c == EOF)
        okloop = NO;
    else {
        //循环体
        ++i;
    }

解答2:

while (i < lim - 1){
    if ( (c = getchar()) != '\n')
        if ( c != EOF)
            //循环体
        else
            break;
    else
        break;
    ++i;
}

 
 

类型转换

隐式类型转换

也被称为自动类型转换。
算术类型转换:通常时把“比较窄的”(精确度低)数据转换为“比较宽的“(精确度高)数据。精确度尽力保持最高。
精确度:char < int < long < folat < double < long double
如:整型 + 浮点型,整型将转换为浮点型。
单精度浮点型 + 双精度浮点型,单精度浮点型将转换为双精度浮点型。
赋值时类型转换:将左边要赋的值转换为右边所指定的类型。
函数参数类型转换:将传入的参数的值转换为参数所指定的类型。
算术类型转换是尽量保持数据的精确性,不丢失信息。
赋值时类型转换和函数类型转换则是要迁就指定的类型,有时需要将精确度高的数据转换为精确度低的数据,这就有肯能丢失信息。
ps:
char类型实际上可以看作范围较小的整型。

显式类型转换

也称强制类型转换。
(类型名)数据/表达式
数据/表达式首先被赋值给类型名指定类型的某个变量,然后再用该变量替换上述整条语句。

ps:
不允许使用无意义(非法)的的表达式。如:将浮点数作为数组下标。
当转换可能会造成信息丢失时,编译器肯能会给出警告。如:将浮点型转换为整型。

题目
编写函数htoi(s),把由十六进制数字组成的字符串(包含可选的前缀0x或0X)转换成与之等价的十进制整数。
注:这里认为字符串以‘\0’作为结束标志,若不是十六进制数则返回0。

int htoi(char s[]){
        int i = 0, num = 0;
        if (s[0] == '0' && (s[1] == 'X' || s[1] == 'x'))
                i = 2;
        while (s[i] != '\0'){
            num *= 16;
                if ( s[i] >= '0' && s[i] <= '9')
                        num += s[i] - '0';
                else if ( s[i] >= 'a' && s[i] <= 'f')
                        num += s[i] - 'a' + 10;
                else if ( s[i] >= 'A' && s[i] <= 'F')
                        num += s[i] - 'A' + 10;
                else{
                        break;
                        num = 0;
                }
                i += 1;
        }
        return num;
 }

 
 

自增运算符与自减运算符

自增操作符++使其操作数+1
自减操作符–使其操作数-1
用在变量前(如:++n),先将n的值+1,在使用n的值。
用在变量后(如:n++),先使用n的值,再将n的值+1。
如:
m = ++n; 等价于 n = n+1;m = n;
m = n++; 等价于 m = n;n = n+1;
即:用在前面先+1,用在后面后+1。
题目1
写一个函数,将字符串s1中任何与字符串s2中字符匹配的字符都删掉。

void method1(char s1[], char s2[]){
        int i, j;
        i = j = 0;
        while (s1[i] != '\0'){
                int k;
                for (k = 0; s2[k] != '\0' && s2[k] != s1[i]; k++);
                if (s2[k] == '\0')
                        s1[j++] = s1[i];
                i++;
        }
        s1[j] = '\0';
}

题目2
编写一个函数,将字符串s2中的字符在字符串s1中第一次出现的位置作为结果返回。若s1中不包含s2中的字符,则返回-1。

int method2(char s1[], char s2[]){
        int i = 0;
        while (s1[i] != '\0'){
                int k;
                for (k = 0; s2[k] != '\0' && s2[k] != s1[i]; k++);
                if (s2[k] != '\0')
                        return i;
                i++;
        }
        return -1;
}

 
 

按位运算

位操作运算符只能作用于整型操作数,即:char,short,int,long

运算符 含义
& 按位与(AND)
| 按位或(OR)
^ 按位异或(XOR)
<< 左移
>> 右移
~ 按位求反

&:按位与运算符,经常用来屏蔽某些二进制位。用来将某几位置为0。
每一位:与0进行&,置为0;与1进行&,保持不变。

|:按位或运算符,经常用来将某些二进制位置为1。用来将某几位置为指定值。
每一位:与0进行|,保持不变;与1进行|,置为1。

^:按位异或运算符,当两个操作数的对应位不相同时将该位置为1,相同置为0。每一位:与0进行^,保持不变;与1进行^,取反。

<<:左移运算符,如:x << 3 将x的二进制表示左移3位,右边空出的3位用0填补。相当于将x乘以8(2^3)。

>>:右移运算符,如:x >> 3 将x的二进制表示右移3位。对于无符号值,左边空出的部分将用0填补。对于有符号值,某些机器对左边空出的部分用符号位填补(算术移位),另一些机器则用0填补(逻辑移位)。

~:用于求整数的二进制反码,二进制位上1变为0,0变为1。
题目1
编写一个函数setbits(x,p,y,n),该函数返回对x执行下列操作后的结果:将x从第p位开始的n个(二进制)位设置为y中最右边的n位的值。

unsigned setbits(unsigned x, int p, int n; unsigned y){
        // 把一个所有位都为1的屏蔽码左移n位
        // ~0 << n
        // 按位取反,得到只有最右边n位为1,其余位为0的屏蔽码
        // ~(~0 << n)
        // 把屏蔽码最右边的n个1左移到第p位处
        // ~(~0 << n) << (p - n + 1)
        // 按位取反,得到只有从p开始n位为0,其余位都为1的屏蔽码
        // ~(~(~0 << n) << (p - n + 1))
        // 将x & 屏蔽码,使得x从第p位开始n位清0
        // x & ~(~(~0 << n) << (p - n + 1)
        // 将y & 从p位开始n位为1,其余位为0的屏蔽码,使得y从第p位开始保持n位,其余位清0
        // y & ~(~0 << n) << (p - n + 1)
        return x & ~(~(~0 << n) << (p - n + 1) | (y & ~(~0 << n)) << (p - n + 1);
}

题目2
编写一个函数invert(x, p, n),该函数返回对x执行下列操作后的结果值:将x中从第p位开始的n个(二进制)位求反,其余位不变。


unsigned invert(unsigned x, int p, int n){
        // 与0进行^(异或),保持不变
        // 与1进行^(异或),取反
        return x ^ (~(~0 << n)) << (p - n + 1));
}

题目3
编写一个函数rightrot(x, n),该函数返回将x循环右移(即从最右端移出的位将从最左端再移入)n个(二进制)位所得到的值。

int wordlength(void){
        int len;
        unsigned v = (unsigned)~0;
        for (len = 1; (v >>= 1) > 0; len++);
        return len;
}

unsigned rightrot(unsigned x, int n){
        int rbit;

        while (n-- > 0){
                rbit = (x & 1) << (wordlength() - 1);
                x >>= 1;
                x |= rbit;
        }
        return x;
}

 
 

赋值运算符

是赋值表达式的缩式
+=,-=,*=,/=,%=,<<=,>>=,&=,^=,|=
如:
x += y 等价于 x = x + y

 
 

条件表达式

使用三元运算符 ? :
expr1 ? exper2 : expr3
首先计算expr1。
若其值不等于0(为真),则计算expr2的值,并将expr2的值作为条件表达式的值。若其值等于0(为假),则计算expr3的值,并将expr3的值作为条件表达式的值。
可以用来替换if else

if (a > b)
    c = a;
else
    c = b;

等价于:
c = (a > b) ? a : b;
题目
用条件表达式写一个将所有大写字母转换为小写字母的函数。

int lower (int c){
        return (c >= 'A' && c <= 'C') ? (c - 'A' + 'a') : c;
}

 
 

运算符优先级与求值次序

同一行的运算符有相同的优先级。
优先级从上往下逐行降低。

运算符 结合性
( ) [ ] -> . 从左至右
! ~ ++ – (type) sizeof() 从右至左
* / % 从左至右
+ - 从左至右
<< >> 从左至右
< <= > >= 从左至右
== != 从左至右
& 从左至右
^ 从左至右
| 从左至右
&& 从左至右
|| 从左至右
?: 从右至左
= += -= *= /= %= &= 从右至左
^= |= <<= >>= 从左至右

猜你喜欢

转载自blog.csdn.net/qq_31730735/article/details/80691173
今日推荐