跳转至

操作符和表达式

本文为《C 与 指针读书笔记》,感兴趣的读者可以去看原书。

C提供了所有你希望编程语言应该拥有的操作符 ,它甚至提供了一些你意想不到的操作符。事实上,C被许多人所诟病的一个缺点就是它品种繁多的操作符。C的这个特点使它很难精通。另一方面,C的许多操作符具有其他语言的操作符无可抗衡的价值,这也是C适用于开发范围极广的应用程序的原因之一。

操作符

算术操作符

C提供了所有常用的算术操作符:

+  -  *  /  %

移位操作符

汇编语言程序员对于移位操作已经是非常熟悉了。对于那些适应能力强的读者,这里作一简单介绍。移位操作只是简单地把一个值的位向左或向右移动。在左移位中,值最左边的几位被丢弃,右边多出来的几个空位则由0补齐。

位操作符

位操作符对它们的操作数的各个位执行AND、OR和XOR(异或)等逻辑操作。

当两个位进行AND操作时,如果两个位都是1,结果为1,否则结果为0。当两个位进行OR操作时,如果两个位都是0,结果为0,否则结果为1。最后,当两个位进行XOR操作时,如果两个位不同,结果为1,如果两个位相同,结果为0。

位操作符有:

&  |  ^

赋值

最后,我们讨论赋值操作符,它用一个等号表示。赋值是表达式的一种,而不是某种类型的语句。所以,只要是允许出现表达式的地方,都允许进行赋值。

赋值操作符把右操作数的值存储于左操作数指定的位置。但赋值也是个表达式,表达式就具有一个值。赋值表达式的值就是左操作数的新值,它可以作为其他赋值操作符的操作数,如下面的语句所示:

a = x = y + 3;

其它操作符

本章还介绍了其他一些操作符

  • 单目操作符
  • 逻辑操作符
  • 条件操作符
  • 逗号操作符
  • 下标引用

布尔值

C并不具备显式的布尔类型,所以使用整数来代替。其规则是:零是假,任何非零值皆为真。

左值和右值

为了理解有些操作符存在的限制,你必须理解左值 (L-value)和右值 (R-value)之间的区别。这两个术语是多年前由编译器设计者所创造并沿用至今,尽管它们的定义并不与C语言严格吻合。

左值就是那些能够出现在赋值符号左边的东西。右值就是那些可以出现在赋值符号右边的东西。

编程练习

练习 1

编写一个程序,从标准输入读取字符,并把它们写到标准输出中。除了大写字母字符要转换为小写字母之外,所有字符的输出形式应该和它的输入形式完全相同。

#include <stdio.h>
#include <ctype.h> // 为了使用tolower函数

int main() {
    int c; // 使用int来存储字符,是因为EOF通常定义为-1,无法用char表示

    // 使用getchar读取单个字符直到EOF
    while((c = getchar()) != EOF) {
        // 如果字符是大写字母,转换为小写
        if(c >= 'A' && c <= 'Z') {
            c = tolower(c);
        }
        // 输出字符
        putchar(c);
    }

    return 0;
}

练习 2

编写一个程序,从标准输入读取字符,并把它们写到标准输出中。所有非字母字符都完全按照它的输入形式输出,字母字符在输出前进行加密。

加密方法很简单:每个字母被修改为在字母表上距其13个位置(前或后)的字母。例如,A被修改为N,B被修改为O,Z被修改为M,以此类推。注意大小写字母都应该被转换

#include <stdio.h>

// 函数声明,用于ROT13加密
char rot13_char(char c);

int main() {
    int c;  // 使用int来接收字符,以便能处理EOF情况

    // 从标准输入中逐字符读取,直到EOF
    while ((c = getchar()) != EOF) {
        // 打印加密后的字符
        putchar(rot13_char(c));
    }

    return 0;
}

// 实现ROT13加密的函数
char rot13_char(char c) {
    // 处理大写字母
    if (c >= 'A' && c <= 'Z') {
        return 'A' + (c - 'A' + 13) % 26;
    }
    // 处理小写字母
    else if (c >= 'a' && c <= 'z') {
        return 'a' + (c - 'a' + 13) % 26;
    }
    // 非字母字符不变
    return c;
}

练习3

编写一个函数,这个函数的返回值是把value的二进制位模式从左到右变换一下后的值,编写函数时要注意不要让它依赖于你的机器上整型值的长度。

#include <stdio.h>

// 函数声明
unsigned int reverse_bits(unsigned int value) {
    unsigned int result = 0;
    unsigned int i;
    for (i = 0; i < sizeof(value) * 8; i++) { // 遍历 value 的每一位
        result <<= 1;  // 将 result 左移一位,为下一位做好空间
        result |= (value & 1); // 将 value 的最低位加到 result 的最低位
        value >>= 1;  // 将 value 右移一位,准备处理下一位
    }
    return result;
}

int main() {
    unsigned int num = 1; // 测试示例
    printf("Original number: %u\n", num);
    unsigned int reversed = reverse_bits(num);
    printf("Reversed bits: %u\n", reversed);

    return 0;
}

最后更新: November 17, 2024