C语言:操作符和表达式

目录

操作符和表达式

1.各种操作符的使用和特点

a.%操作符能作用于浮点数吗?

b.位操作符都有哪些?

c.移位操作符可以移动负数吗?

d.异或操作符是怎么计算的?

e.列举几个单目操作符

f. !和 ~ 这两个操作符有什么区别?

g. & 和 && 有什么区别?

h. | 和 || 有什么区别?

2.操作符的优先级和结合性

操作符的优先级和结合性是怎么使用的呢?

 3.类型转换

a.整型提升

--什么是整型提升?

--如何进行整型提升?

b.算数转换

什么是算数转换?

c.强制类型转换

4.表达式的求值

a.C语言中有唯一的计算结果吗?


板块:

  • 各操作符的使用和特点
  • 操作符的优先级和结合性
  • 类型转换
  • 表达式的求值

提问:

  • %(取余)操作符能作用于浮点数吗?
  • 位操作符有哪些?
  • 移位操作符可以移动负数位吗?
  • 异或操作符是怎么计算的?
  • 列举几个单目操作符
  • !和 ~ 这两个操作符有什么区别?
  • & 和 && 这两个操作符有什么区别?
  • | 和 || 有什么区别?

  • 操作符优先级和结合性怎么使用?

  • 整型提升是什么?
  • 如何整型提升?
  • 什么是算数转换?
  • 强制类型转换

  • C语言中有唯一的计算结果吗?

操作符和表达式

1.各种操作符的使用和特点

a.%操作符能作用于浮点数吗?

   % 操作符(取模操作符)不能直接用于浮点数。该操作符用于取两个整数的模(余数),而不是浮点数。

b.位操作符都有哪些?

       C 语言中的位操作符用于对整数的二进制位进行操作。不能作用浮点数。

        

        1.按位与(AND):&

  • 对两个操作数的对应位执行逻辑与操作,只有当两个位都为 1 时,结果位才为 1。

       2.按位或(OR):|

  • 对两个操作数的对应位执行逻辑或操作,只要两个位中有一个为 1,结果位就为 1。

       3.按位异或(XOR):^

  • 对两个操作数的对应位执行逻辑异或操作,只有当两个位不相同时,结果位才为 1。

       4. 按位取反(NOT):~

  • 对操作数的每个位执行逻辑取反操作,即 0 变为 1,1 变为 0。

       5. 左移(左位移):<<

  • 将一个操作数的所有位向左移动指定的位数。左侧空出的位用零填充。

       6.右移(右位移):>>

  • 将一个操作数的所有位向右移动指定的位数。(逻辑位移)对于无符号数,右侧空出的位用零填充;对于有符号数,右侧空出的位用符号位填充(算符位移)。

c.移位操作符可以移动负数吗?

        移位操作符可以用于移动有符号整数(负数),但是移位的结果可能与你期望的不同,对有符号整数,右移会补充它的符号位,造成结果不同。

  例如,假设使用的是有符号的 signed int 数据类型,-5 的二进制表示为(负数补码表示)

           10000000000000000000000000000101(原码)

    11111111111111111111111111111010(反码)原码去反

           11111111111111111111111111111011(补码)反码+1

           如果对它进行右移操作 result = -5 >> 2;,结果将是 -2,即二进制表示                               11111111111111111111111111111110。右移操作会将符号位扩展到右侧。

        对于左移(<<)操作符,对于有符号整数,左移操作的行为是未定义的,这是因为左移可能导致有符号整数的溢出。因此,在处理有符号整数时,应格外小心使用左移操作符。

        在使用移位操作符时,使用无符号整数类型进行移位操作,以确保得到预期的结果。

d.异或操作符是怎么计算的?

异或操作的规则如下:同0异1

  • 如果两个操作数的对应位都是相同的(都为 0 或都为 1),则结果位为 0。
  • 如果两个操作数的对应位不同(一个为 0,另一个为 1),则结果位为 1。

示例:

A = 10101010
B = 11001100

A ^ B = 01100110

异或操作符满足规律:

  • 结合律:对于任意三个数 A、B 和 C,异或操作符满足结合律。即 (A ^ B) ^ C 等于 A ^ (B ^ C)。这意味着在进行多个异或操作时,可以按任意顺序进行括号分组,结果是相同的。
  • 交换律:对于任意两个数 A 和 B,异或操作符满足交换律。即 A ^ B 等于 B ^ A。这意味着异或操作可以改变操作数的顺序,结果不受影响。
  • 零元素:对于任意数 A,与零进行异或操作的结果为 A 本身,即 A ^ 0 = A。
  • 自反性:对于任意数 A,与自身进行异或操作的结果为零,即 A ^ A = 0。这是因为在异或操作中,相同的位会得到零

异或操作在计算机中有很多应用,例如:

  • 交换两个变量的值,可以使用异或操作,而不需要额外的临时变量。
  • 判断两个二进制数中有多少位不同。
  • 实现简单的加密算法和错误检测。

e.列举几个单目操作符

!   逻辑反操作
负值
+ 正值
sizeof 操作数的类型长度(以字节为单位)
~ 对一个数的二进制按位取反
-- 前置、后置--
++ 前置、后置++
* 间接访问操作符(解引用操作符)
(类型) 强制类型转换
& 取地址

f. !和 ~ 这两个操作符有什么区别?

逻辑非操作符 !

  • ! 是逻辑非操作符,用于对布尔值进行逻辑取反操作。它将一个布尔表达式或值转换为相反的逻辑值。如果操作数为真(非零),则取反后为假(0);如果操作数为假(0),则取反后为真(非零)。

示例:

int x = 5;
if (!x) {
    // 如果 x 的值为 0,则执行此代码块
}

按位取反操作符 ~

  • ~ 是按位取反操作符,用于对整数的每个位执行逻辑取反操作。它将一个整数的每个二进制位从 0 变为 1,从 1 变为 0。按位取反操作符 ~ 只能用于整数类型(包括有符号整数和无符号整数)。

示例:

int x = 5;
int result = ~x;

在上面的示例中,~x 将 x 的位取反,并将结果赋值给 result

如果 x 的二进制表示为 00000000 00000000 00000000 00000101

 则 ~x 的二进制表示为 11111111 11111111 11111111 11111010

总结:! 是逻辑非操作符,用于对布尔值进行逻辑取反操作,而 ~ 是按位取反操作符,用于对整数的每个位进行逻辑取反操作。

g. & 和 && 有什么区别?

逻辑与操作符 &&

  • && 是逻辑与操作符,用于对两个布尔表达式或值进行逻辑与运算。它要求两个操作数都为真(非零)时,结果为真(非零),否则为假(0)。&& 操作符用于布尔类型的操作数。

示例:

int a = 5;
int b = 3;
if (a > 0 && b > 0) {
    // 如果 a 和 b 的值都大于 0,则执行此代码块
}

位与操作符 &

  • & 是位与操作符,用于对两个操作数的对应位执行逻辑与操作。它将两个操作数的对应位进行逻辑与运算,只有当两个位都为 1 时,结果位才为 1,否则为 0。& 操作符可以用于整数类型(包括有符号整数和无符号整数)。

示例:

int a = 5;   // 二进制:00000000 00000000 00000000 00000101
int b = 3;   // 二进制:00000000 00000000 00000000 00000011
int result = a & b;  // 二进制结果:00000000 00000000 00000000 00000001,十进制结果:1

总结:& 是位与操作符,用于对两个整数的对应位执行逻辑与操作,而 && 是逻辑与操作符,用于对两个布尔表达式或值进行逻辑与操作。它们在功能和使用场景上有明显的区别。

h. | 和 || 有什么区别?

逻辑或操作符 ||

  • || 是逻辑或操作符,用于对两个布尔表达式或值进行逻辑或运算。它要求至少一个操作数为真(非零)时,结果为真(非零),否则为假(0)。|| 操作符用于布尔类型的操作数。

示例:

int a = 5;
int b = 3;
if (a > 0 || b > 0) {
    // 如果 a 和 b 的值中至少有一个大于 0,则执行此代码块
}

位或操作符 |

  • | 是位或操作符,用于对两个操作数的对应位执行逻辑或操作。它将两个操作数的对应位进行逻辑或运算,只要其中一个位为 1,结果位就为 1,否则为 0。| 操作符可以用于整数类型(包括有符号整数和无符号整数)。

示例:

int a = 5;   // 二进制:00000000 00000000 00000000 00000101
int b = 3;   // 二进制:00000000 00000000 00000000 00000011
int result = a | b;  // 二进制结果:00000000 00000000 00000000 00000111,十进制结果:7

总结:| 是位或操作符,用于对两个整数的对应位执行逻辑或操作,而 || 是逻辑或操作符,用于对两个布尔表达式或值进行逻辑或操作。它们在功能和使用场景上有明显的区别。

2.操作符的优先级和结合性

操作符的优先级和结合性是怎么使用的呢?

C语言:操作符和表达式_第1张图片

 3.类型转换

a.整型提升

--什么是整型提升?

        整型提升是指在某些表达式中,较小的整数类型被自动转换为较大的整数类型的过程。这种自动类型转换是为了保证表达式中的操作数类型一致,以便进行正确的运算。

--如何进行整型提升?

  • 整形提升是按照变量的数据类型的符号位来提升的

        整型提升是在表达式求值期间自动执行的,开发人员不需要显式地编写类型转换代码。它确保了在表达式中不同类型的操作数能够以一致的方式进行计算,避免了类型不匹配导致的错误。

        示列:

short a = 10;
int b = 20;
int result = a + b;

        在上述示例中,变量 a 的类型为 short,变量 b 的类型为 char。在表达式 a + b 中,b 的类型会被提升为 int,以保证 ab 的类型一致进行相加操作。

        整型提升是在特定的上下文中发生的,例如算术运算、比较操作、位操作等。在其他情况下,例如赋值操作,整型提升可能不会发生。

        //负数的整形提升:
        char c1 = -1;
        变量c1的二进制位(补码)中只有8个比特位:
        1111111
        因为 char 为有符号的 char
        所以整形提升的时候,高位补充符号位,即为1
        提升之后的结果是:
        11111111111111111111111111111111


        //正数的整形提升
        char c2 = 1;
        变量c2的二进制位(补码)中只有8个比特位:
        00000001
        因为 char 为有符号的 char
        所以整形提升的时候,高位补充符号位,即为0
        提升之后的结果是:
        00000000000000000000000000000001
        //无符号整形提升,高位补0

b.算数转换

什么是算数转换?

        算术转换:也称为数值提升,是指在表达式中进行运算时,将不同类型的操作数自动转换为一个公共类型的过程。

        

        算术转换的规则如下:低向高转换

  • 如果两个操作数具有相同的类型(如两个 int 类型的操作数),则无需转换。
  • 如果一个操作数的类型为 long double,则另一个操作数会被转换为 long double
  • 如果一个操作数的类型为 double,则另一个操作数会被转换为 double
  • 如果一个操作数的类型为 float,则另一个操作数会被转换为 float
  • 如果一个操作数的类型为整数类型(如 charshortint),而另一个操作数为浮点类型(如 floatdouble),则整数类型会被转换为浮点类型。
  • 如果一个操作数的类型为有符号整数类型(如 int),而另一个操作数为无符号整数类型(如 unsigned int),则有符号整数会被转换为无符号整数。
  • 如果两个操作数的类型为整数类型,但它们的宽度不同(如 int 和 long),则较小的整数类型会被转换为较大的整数类型。

c.强制类型转换

        强制类型转换:是一种显式地将一个数据类型转换为另一个数据类型的操作。它允许程序员手动指定需要进行的类型转换,以满足特定的需求。

        语法:

        

(type) expression

        其中,type 表示要转换的目标类型,而 expression 则是需要进行类型转换的表达式或变量。

4.表达式的求值

a.C语言中有唯一的计算结果吗?

        在 C 语言中,计算结果通常是确定的,即给定相同的输入和操作,同一个表达式的计算结果应该是唯一的。这是因为 C 语言是一种确定性的编程语言,按照语言规范定义了各种运算符和操作的行为。

        例如,对于简单的算术运算符(如加法、减法、乘法、除法等)和位运算符(如按位与、按位或、异或等),给定相同的操作数,计算结果是确定的,并且每次运算都会得到相同的结果。

        然而,需要注意的是,在一些特定情况下,C 语言中的一些操作可能会产生未定义的行为。例如:

  • 除以零:在 C 语言中,除法运算符 / 用于执行除法操作。当除数为零时,这将导致未定义的行为,因为在数学中除以零是没有定义的。

  • 溢出:如果计算结果超过了某个类型所能表示的范围,会发生溢出。溢出会导致未定义的行为,因为 C 语言规范没有明确定义溢出的结果。

        此外,还有一些特殊情况需要注意,如浮点数的舍入误差和计算顺序的影响。在进行浮点数计算时,由于浮点数的内部表示方式和精度限制,可能会产生舍入误差,导致微小的差异。此外,C 语言规定了一些运算符的计算顺序,但对于不同的表达式,编译器可能会对其进行优化和重排,从而影响计算的顺序。

       总结:大部分情况下,C 语言中的计算结果是确定的和可预测的。但在某些特殊情况下,特别是涉及未定义行为的情况下,计算结果是不确定的,

你可能感兴趣的:(C语言,c语言,开发语言,笔记)