C语言操作符详解

系列文章目录

第一章 C语言基础知识

第二章 C语言控制语句

第三章 C语言函数详解

第四章 C语言数组详解

第五章 C语言操作符详解

第六章 C语言指针详解


文章目录

1. 操作符分类

2. 算术操作符

2.1 加法操作符 +

2.2 减法操作符 -

2.3 乘法操作符 *

2.4 除法操作符 /

2.5 取模操作符 %

3. 移位操作符

3.1 左移位操作符 (<<)

3.2 右移位操作符 (>>)

4. 位操作符

4.1 位与操作符 &

 4.2 位或操作符 |

 4.3 位异或操作符 ^

 4.4 位非操作符 ~

 4.5 练习

5. 赋值操作符

5.1 基本赋值操作符

5.2 复合赋值操作符

+=(加后赋值)

-=(减后赋值)

*=(乘后赋值)

/=(除后赋值)

%=(模后赋值)

<<=(左移后赋值)

>>=(右移后赋值)

&=(位与后赋值)

|=(位或后赋值)

6. 单目操作符

6.1 单目操作符介绍

逻辑非 !

位非 ~

正号 +

负号 -

前置递增 ++

前置递减 --

取地址操作符 &

间接访问(解引用)操作符 *

sizeof 运算符

sizeof 在数组参数中的表现

6.2 练习

7. 关系操作符

等于 (==):

不等于 (!=):

大于 (>):

小于 (<):

大于等于 (>=):

小于等于 (<=):

8. 逻辑操作符

逻辑与 (&&):

按位与 (&)

逻辑或 (||):

按位或 (|)

练习:

9. 条件操作符

语法和结构

10. 逗号表达式

10.1 语法

10.2 代码示例

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

11.1 下标引用 ([])

11.2 函数调用 (())

11.3 结构成员访问 (. 和 ->)

12. 表达式求值

12.1 操作符的优先级

12.2 隐式类型转换

12.3 显式类型转换


1. 操作符分类

算术操作符
移位操作符
位操作符
赋值操作符
单目操作符
关系操作符
逻辑操作符
条件操作符
逗号表达式
下标引用、函数调用和结构成员

2. 算术操作符

在 C 语言中,算术操作符用于执行基本的数学运算,包括加法、减法、乘法、除法和取模运算。这些操作符是 C 语言中最常用的操作符之一,它们可以应用于整型和浮点型数据。下面详细介绍每个算术操作符及其用途:

2.1 加法操作符 +

加法操作符用于计算两个数的总和。当操作数为数值类型时,结果是它们的算术和。

int a = 5;
int b = 3;
int sum = a + b;  // sum 的值为 8

2.2 减法操作符 -

减法操作符用于计算两个数的差。它从第一个操作数中减去第二个操作数。

int a = 5;
int b = 3;
int difference = a - b;  // difference 的值为 2

2.3 乘法操作符 *

乘法操作符用于计算两个数的乘积。

int a = 5;
int b = 3;
int product = a * b;  // product 的值为 15

2.4 除法操作符 /

除法操作符用于两个数的除法运算。需要注意的是,如果两个操作数都是整数,那么执行的将是整数除法,结果将被截断为整数。如果操作数中至少有一个是浮点数,那么执行的将是浮点除法,结果是浮点数。

int a = 10;
int b = 3;
int quotient = a / b;  // quotient 的值为 3(整数除法)

double c = 10.0;
double result = c / b;  // result 的值为 3.333333(浮点除法)

2.5 取模操作符 %

取模操作符用于计算两个整数相除的余数。注意,取模操作符只能用于整数。

int a = 10;
int b = 3;
int remainder = a % b;  // remainder 的值为 1

3. 移位操作符

在 C 语言中,移位操作符用于将位模式(即二进制数)向左或向右移动指定的位数。这些操作符非常有用,特别是在底层编程、优化和处理位级操作时。C 语言提供了两种类型的移位操作符:左移位操作符 (<<) 和右移位操作符 (>>)。

3.1 左移位操作符 (<<)

 左移位操作符 (<<) 将位模式向左移动指定的位数。在左移时,最右边的空位被填充为0。左移一位的效果等同于将数值乘以2,因此左移操作经常被用来高效地计算乘法。

result = operand << num_bits;
  • operand 是要移动的数。
  • num_bits 是要移动的位数。
  • result 是操作后的结果。
unsigned int a = 3;     // 二进制表示为 0000 0011
unsigned int result = a << 2;  // 结果为 0000 1100,相当于 3 * 2^2 = 12

3.2 右移位操作符 (>>)

右移位操作符 (>>) 将位模式向右移动指定的位数。右移的填充位取决于数字的类型(有符号还是无符号):

  • 对于无符号数,空缺位将填充0。
  • 对于有符号数,右移通常是算术右移,空缺位填充符号位(即最左边的位),以保持数的符号不变。
result = operand >> num_bits;
  • operand 是要移动的数。
  • num_bits 是要移动的位数。
  • result 是操作后的结果。

示例代码:

unsigned int a = 12;     // 二进制表示为 0000 1100
unsigned int result = a >> 2;  // 结果为 0000 0011,相当于 12 / 2^2 = 3

int b = -13;             // 例如,二进制可能表示为 1111 0011(取决于具体的系统)
int result_neg = b >> 2; // 结果可能为 1111 1100,注意符号位的保持
  • 快速乘除法:使用移位操作来快速实现乘以2的幂或除以2的幂。
  • 位域操作:直接操作数据的位模式,例如在设定或清除特定的标志位时。
  • 数据打包与解包:在网络通信中对数据进行打包和解包。
  • 资源优化:在资源有限的设备上优化性能和内存使用。

注意:

  • 移位操作数(num_bits)过大可能导致未定义的行为。确保移位的位数小于操作数的位宽。
  • 对于负整数的右移操作,行为依赖于编译器和平台,因为 C 标准没有规定负数的右移行为。
  • 滥用移位操作可能导致数据丢失,特别是当超出数据类型的位长度时。

4. 位操作符

位操作符在 C 语言中用于执行位级操作,这意味着这些操作是直接在操作数的二进制表示上进行的。C 语言提供了几个位操作符:位与(AND)、位或(OR)、位异或(XOR)和位非(NOT)。

4.1 位与操作符 &

位与操作符用于对两个操作数进行逐位与操作。只有在两个相应的位都为1时,结果的那位才为1,否则为0。

result = operand1 & operand2;

代码示例:

int a = 12;  // 二进制表示为 1100
int b = 10;  // 二进制表示为 1010
int result = a & b;  // 结果为 1000 (8)

 4.2 位或操作符 |

位或操作符用于对两个操作数进行逐位或操作。如果两个相应的位中至少有一个为1,那么结果的那位就为1,否则为0。

result = operand1 | operand2;

代码示例:

int a = 12;  // 二进制表示为 1100
int b = 10;  // 二进制表示为 1010
int result = a | b;  // 结果为 1110 (14)

 4.3 位异或操作符 ^

位异或操作符用于对两个操作数进行逐位异或操作。如果两个相应的位不同,那么结果的那位就为1;如果相同,那么结果的那位就为0。

result = operand1 ^ operand2;

代码示例:

int a = 12;  // 二进制表示为 1100
int b = 10;  // 二进制表示为 1010
int result = a ^ b;  // 结果为 0110 (6)

 4.4 位非操作符 ~

位非操作符(或称位取反)是一个单目操作符,用于对操作数的每一位进行取反操作。1变0,0变1。

result = ~operand;

 代码示例:

int a = 12;  // 二进制表示为 1100
int result = ~a;  // 结果为 ...11110011 (依赖于数据类型和系统,假设是32位int,则为 -13)

 4.5 练习

 编写代码实现:求一个整数存储在内存中的二进制中1的个数。

方法 1: 基于除以2的循环

这种方法只适用于非负整数。对于负数,由于整数除法的特性(舍去小数部分),可能会导致无限循环。

#include <stdio.h>
int main()
{
    int num = 10;         // 初始化数字
    int count = 0;        // 用于计数num的二进制表示中1的个数
    while (num)           // 当num不为0时,执行循环
    {
        if (num % 2 == 1) // 如果当前最低位是1,计数器增加
            count++;
        num = num / 2;    // num除以2,右移一位,丢弃最低位
    }
    printf("二进制中1的个数 = %d\n", count);
    return 0;
}

方法 2: 位掩码检查

这种方法正确处理了正数和负数。循环固定32次,这对于32位整数是有效的,但对于不同的数据类型可能不适用或效率不高。

#include <stdio.h>
int main()
{
    int num = -1;         // 初始化数字,这里是-1
    int count = 0;        // 计数器
    for (int i = 0; i < 32; i++) // 循环检查每一位是否为1
    {
        if (num & (1 << i)) // 将1左移i位,使用位与操作检查第i位是否为1
            count++;
    }
    printf("二进制中1的个数 = %d\n", count);
    return 0;
}

方法3:

这种方法被认为是最高效的方法之一,因为它的迭代次数直接依赖于1的个数。每次操作都清除最右边的1,直到num变为0。它同样适用于正数和负数。

#include <stdio.h>
int main()
{
    int num = -1;          // 初始化数字为-1
    int count = 0;         // 计数器
    while (num)            // 当num不为0时
    {
        count++;           // 增加计数器
        num = num & (num - 1); // 清除最低位的1
    }
    printf("二进制中1的个数 = %d\n", count);
    return 0;
}

5. 赋值操作符

赋值操作符在 C 语言中用于设置变量的值。最基本的赋值操作符是单一的等号(=),这些操作符结合了算术操作和赋值操作,以简化常见的操作。

5.1 基本赋值操作符

等号是最基本的赋值操作符,用于将右侧表达式的值赋给左侧的变量。

代码示例:

int a = 5;  // 将5赋值给整数变量a

5.2 复合赋值操作符

复合赋值操作符结合了其他操作(如加法、减法、乘法等)和赋值,这样可以在执行操作的同时更新变量的值。

  • +=(加后赋值)

将右侧的值加到左侧的变量上,然后将结果赋值给左侧的变量。

int a = 5;
a += 3;  // 等同于 a = a + 3; a现在是8
  • -=(减后赋值)

从左侧的变量中减去右侧的值,然后将结果赋值给左侧的变量。

int a = 5;
a -= 3;  // 等同于 a = a - 3; a现在是2
  • *=(乘后赋值)

将左侧的变量与右侧的值相乘,然后将结果赋值给左侧的变量。

int a = 5;
a *= 3;  // 等同于 a = a * 3; a现在是15
  • /=(除后赋值)

将左侧的变量除以右侧的值,然后将结果赋值给左侧的变量。

int a = 15;
a /= 3;  // 等同于 a = a / 3; a现在是5
  • %=(模后赋值)

用左侧的变量除以右侧的值计算余数,然后将结果赋值给左侧的变量。

int a = 16;
a %= 3;  // 等同于 a = a % 3; a现在是1
  • <<=(左移后赋值)

将左侧的变量左移指定的位数,然后将结果赋值给左侧的变量。

int a = 1;
a <<= 3;  // 等同于 a = a << 3; a现在是8
  • >>=(右移后赋值)

将左侧的变量右移指定的位数,然后将结果赋值给左侧的变量。

int a = 16;
a >>= 3;  // 等同于 a = a >> 3; a现在是2
  • &=(位与后赋值)

对左侧的变量和右侧的值进行位与操作,然后将结果赋值给左侧的变量。

int a = 12;
a ^= 5;  // 等同于 a = a ^ 5; a现在是9
  • |=(位或后赋值)

对左侧的变量和右侧的值进行位或操作,然后将结果赋值给左侧的变量。

int a = 12;
a |= 5;  // 等同于 a = a | 5; a现在是13

6. 单目操作符

6.1 单目操作符介绍

在 C 语言中,单目操作符是只需要一个操作数的操作符。它们直接作用于其后的变量或表达式,执行各种运算。单目操作符包括几种常见类型,如逻辑非、位非、正号、负号、增量和减量操作符。

  • 逻辑非 !

逻辑非操作符 ! 用于反转其操作数的布尔值。如果操作数为 0(假),则结果为 1(真);如果操作数为非零,则结果为 0(假)。

int a = 0;
int result = !a;  // result 的值为 1,因为 !0 为真
  • 位非 ~

位非操作符 ~ 对整型操作数的每一位进行逻辑非操作,即将所有的 0 变为 1,所有的 1 变为 0

int a = 5;         // 二进制表示为 0000 0101
int result = ~a;   // 结果为 1111 1010 (在一个字节的二进制表示中)
  • 正号 +

正号操作符 + 是单目操作符中最直观的一个,它表明其操作数是正值。在大多数情况下,这个操作符对操作数没有实际影响。

int a = 5;
int result = +a;  // result 的值仍然为 5
  • 负号 -

负号操作符 - 用于改变其操作数的符号。如果操作数是正的,使用负号后变为负的;如果是负的,则变为正的。

int a = 5;
int result = -a;  // result 的值为 -5
  • 前置递增 ++

前置递增操作符 ++ 用于将其操作数增加 1,并返回增加后的值。

int a = 5;
int result = ++a;  // a 和 result 都变为 6
  • 前置递减 --

前置递减操作符 -- 用于将其操作数减少 1,并返回减少后的值。

int a = 5;
int result = --a;  // a 和 result 都变为 4
  • 取地址操作符 &

取地址操作符返回其操作数的内存地址。

int a = 5;
int *ptr = &a;  // ptr 现在指向 a 的地址
  • 间接访问(解引用)操作符 *

解引用操作符用于访问指针指向的变量的值。

int a = 5;
int *ptr = &a;
int value = *ptr;  // value 是 5
  • sizeof 运算符

sizeof 可以用来测量变量、数据类型、表达式或数组的大小。结果的类型是 size_t,这是一个在 <stddef.h> 头文件中定义的无符号整型。

int arr[10];
size_t arrSize = sizeof(arr);             // 返回整个数组的大小,如果int是4字节,则返回40字节
size_t numElements = sizeof(arr) / sizeof(arr[0]); // 计算数组中的元素数量,结果是10

sizeof 在数组参数中的表现

当数组作为参数传递给函数时,数组会退化为指向其首元素的指针,因此在函数内部使用 sizeof 并不会返回数组的实际大小,而是返回指针的大小。

void printArraySize(int arr[]) {
    size_t size = sizeof(arr);  // 这里返回的是指针的大小,而不是数组的大小
    printf("Array size inside function: %zu bytes\n", size);
}

int main() {
    int myArray[10];
    printf("Array size in main: %zu bytes\n", sizeof(myArray));  // 正确显示数组大小
    printArraySize(myArray);  // 显示指针大小
    return 0;
}

6.2 练习

实现一个功能,其中包含:

  1. 初始化一个整数数组。
  2. 使用指针遍历数组,计算数组元素的总和。
  3. 打印数组中每个元素的地址和值。
  4. 打印数组的总大小和单个元素的大小。
  5. 动态调整数组元素的值。
#include <stdio.h>

int main() {
    int numbers[] = {10, 20, 30, 40, 50};
    int *ptr = numbers;  // ptr 指向数组的第一个元素
    int total = 0;       // 用于存储数组元素的总和
    size_t size = sizeof(numbers) / sizeof(numbers[0]);  // 数组元素的数量

    // 使用指针遍历数组并计算总和
    for (int i = 0; i < size; ++i) {
        total += *ptr;  // 累加指针指向的当前元素
        ptr++;          // 移动指针到下一个元素
    }

    // 重置指针到数组开头
    ptr = numbers;

    // 打印数组的每个元素的地址和值
    printf("Array elements and their addresses:\n");
    for (int i = 0; i < size; ++i) {
        printf("Element %d: %d, Address: %p\n", i, *ptr, (void*)ptr);
        *ptr++ += 5;  // 增加当前元素的值并将指针移到下一个元素
    }

    // 打印数组总大小和单个元素的大小
    printf("Total size of array: %zu bytes\n", sizeof(numbers));
    printf("Size of one element: %zu bytes\n", sizeof(numbers[0]));

    // 再次打印修改后的数组
    printf("Modified array:\n");
    for (int i = 0; i < size; ++i) {
        printf("%d ", numbers[i]);
    }
    printf("\n");

    // 打印总和
    printf("Total sum of elements: %d\n", total);

    return 0;
}

7. 关系操作符

关系操作符用于比较两个值的大小或相等性,根据比较的结果返回布尔值(0 表示假,非 0(通常是 1)表示真)。

等于 (==)

  • 比较两个操作数是否相等。
  • 如果相等,则返回 1;如果不相等,则返回 0

不等于 (!=)

  • 比较两个操作数是否不相等。
  • 如果不相等,则返回 1;如果相等,则返回 0

大于 (>)

  • 比较左操作数是否大于右操作数。
  • 如果左边大于右边,则返回 1;否则返回 0

小于 (<)

  • 比较左操作数是否小于右操作数。
  • 如果左边小于右边,则返回 1;否则返回 0

大于等于 (>=)

  • 比较左操作数是否大于或等于右操作数。
  • 如果左边大于或等于右边,则返回 1;否则返回 0

小于等于 (<=)

  • 比较左操作数是否小于或等于右操作数。
  • 如果左边小于或等于右边,则返回 1;否则返回 0

8. 逻辑操作符

逻辑操作符用于执行布尔逻辑运算,这些操作符通常用于组合多个条件表达式,以控制程序的决策流程。逻辑操作符的结果总布尔类型,即 0(假)或 1(真)。

逻辑与 (&&)

  • 类型:布尔逻辑操作符。
  • 操作:比较两个条件或表达式,并返回一个布尔值。只有当两个操作数都为真(非零)时,结果才为真(1)。否则,结果为假(0)。
  • 短路特性:如果第一个操作数为假(0),则不评估第二个操作数,因为无论第二个操作数是什么,整个表达式的结果都已确定为假。
if (a > 0 && b > 0) {
    // 仅当a和b都大于0时,执行代码块
}

按位与 (&)

  • 类型:位操作符。
  • 操作:对两个数的每一位进行与操作。只有对应的两位都是1时,结果位才是1,否则是0。
int a = 5; // 二进制:0101
int b = 3; // 二进制:0011
int result = a & b; // 结果为1,二进制:0001

逻辑或 (||)

  • 类型:布尔逻辑操作符。
  • 操作:比较两个条件或表达式,并返回一个布尔值。如果至少一个操作数为真(非零),结果就为真(1)。只有当两个操作数都为假(0)时,结果才为假(0)。
  • 短路特性:如果第一个操作数为真,那么不评估第二个操作数,因为整个表达式的结果已确定为真。
if (a > 0 || b > 0) {
    // 只要a或b任一大于0,执行代码块
}

按位或 (|)

  • 类型:位操作符。
  • 操作:对两个数的每一位进行或操作。如果对应的任何一位是1,结果位就是1,否则是0。
int a = 5; // 二进制:0101
int b = 3; // 二进制:0011
int result = a | b; // 结果为7,二进制:0111

练习:

#include <stdio.h>
int main()
{
    int i = 0, a = 0, b = 2, c = 3, d = 4; // 初始化变量i, a, b, c, d

    // 使用逻辑与操作符。逻辑与的短路特性意味着如果发现任何一个操作数结果为假,则停止计算
    // a++ 的值是 0 (后置递增,使用旧值),因此整个表达式的结果为假,并且后面的表达式不会执行
    i = a++ && ++b && d++; // a++ 为0, 所以 i = 0, 递增停止在 ++b

    printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);
    return 0;
}

逻辑与操作符的短路特性

在这个表达式中,a++ 是后置递增,意味着它的值在表达式计算之前使用。因为 a 的初始值为 0,所以 a++ 返回 0,并且在表达式计算后 a 变成了 1。由于 && 操作符的短路特性,一旦 a++ 返回 0(假),后面的表达式 ++b 和 d++ 都不会被执行。

变量的最终值

  • a = 1:因为 a++ 是后置递增。
  • b = 2:++b 没有执行,因此 b 的值没有改变。
  • c = 3:变量 c 在这段代码中没有被修改。
  • d = 4:由于短路,d++ 没有执行。

9. 条件操作符

语法和结构

expression1 ? expression2 : expression3
  • expression1:这是一个布尔表达式,其结果必须是真(非零)或假(零)。
  • expression2:如果 expression1 为真(非零),则计算并返回此表达式的值。
  • expression3:如果 expression1 为假(零),则计算并返回此表达式的值。

代码示例:

int age = 20;
const char* status = age >= 18 ? "adult" : "minor";
printf("You are an %s.\n", status);

在这个例子中,条件 age >= 18 被评估。因为 age 是 20,条件为真,所以 status 被赋值为 "adult"。如果 age 小于 18,status 将被赋值为 "minor"。

10. 逗号表达式

10.1 语法

(expression1, expression2, expression3, ..., expressionN)

其中 expression1 到 expressionN-1 都将被评估并执行,但它们的结果被丢弃,只有 expressionN 的结果被返回和使用。

10.2 代码示例

多变量初始化

#include <stdio.h>

int main() {
    int a, b, c;
    
    for (a = 0, b = 10, c = 20; a < 10; a++, b--, c += 2) {
        printf("a: %d, b: %d, c: %d\n", a, b, c);
    }

    return 0;
}

在这个示例中,逗号操作符用于在循环的初始化和迭代部分执行多个表达式。每次循环中,变量 a 递增 1,变量 b 递减 1,变量 c 增加 2。循环从 a = 0 开始,并在 a 小于 10 时结束。

表达式分组

#include <stdio.h>

int main() {
    int x = 1, y = 2, z = 3;
    int result;

    result = (x += 10, y += 10, z += 10);
    printf("result: %d, x: %d, y: %d, z: %d\n", result, x, y, z);

    return 0;
}

在这个示例中,每个变量都增加了 10,但 result 变量的值是最后一个表达式 z += 10 的结果,因此结果是 13。变量 x、y 和 z 分别从其初始值(1, 2, 3)增加 10。

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

11.1 下标引用 ([])

下标引用操作符用于访问数组中的元素。数组可以被视为一系列连续存储的元素,下标引用允许我们通过索引来访问这些元素。索引通常从0开始,表示数组的第一个元素。

int arr[10]; // 声明一个整数数组,包含10个元素
arr[0] = 5;  // 将数组的第一个元素设置为5
printf("First element: %d\n", arr[0]); // 打印数组的第一个元素

11.2 函数调用 (())

函数调用操作符用于执行一个函数。在 C 语言中,函数定义包含返回类型、函数名称和参数列表。函数调用需要提供函数名称和括号中的参数,以执行函数并返回结果。

#include <stdio.h>

int add(int x, int y) {
    return x + y;
}

int main() {
    int result = add(5, 3); // 调用函数add,传递参数5和3
    printf("Sum: %d\n", result);
    return 0;
}

11.3 结构成员访问 (. 和 ->)

C 语言允许定义复合数据类型,称为结构体(struct),它可以包含多个不同类型的数据项。结构成员访问操作符用于访问结构体变量的成员。

  • . 操作符用于直接访问结构体的成员。
  • -> 操作符用于通过结构体指针访问其成员。
#include <stdio.h>

typedef struct {
    int x;
    int y;
} Point;

int main() {
    Point p = {10, 20}; // 创建一个Point类型的结构体变量p
    Point *ptr = &p;    // 创建一个指向p的指针ptr

    printf("p.x: %d\n", p.x); // 使用.操作符访问p的成员x
    printf("ptr->y: %d\n", ptr->y); // 使用->操作符访问ptr指向的成员y
    return 0;
}

p.x: 10
ptr->y: 20

12. 表达式求值

12.1 操作符的优先级

操作符的优先级决定了在表达式中哪些操作先被执行。在 C 语言中,不同的操作符具有不同的优先级。例如,乘法和除法操作符 (*/) 的优先级高于加法和减法操作符 (+-)。这意味着在表达式 a + b * c 中,先执行 b * c,然后将结果与 a 相加。

操作符的结合性

当表达式中有多个相同优先级的操作符时,操作符的结合性决定了它们的求值顺序。大多数二元操作符在 C 语言中是左结合的,意味着这些操作符会从左向右求值。例如,在表达式 a - b - c 中,首先计算 a - b 的结果,然后从该结果中减去 c

12.2 隐式类型转换

在求值过程中,操作数可能需要进行类型转换以匹配另一个操作数的类型,或者适应操作符的期望。这称为隐式类型转换或强制类型转换。例如:

算术转换:当操作数类型不同时,较“小”的类型(如 int)可能会被提升为较“大”的类型(如 double)来避免精度损失。
整型提升:小整数类型(如 char 和 short)通常在参与表达式计算时提升为 int 或 unsigned int。

示例 1: 算术运算中的隐式转换

#include <stdio.h>

int main() {
    int i = 10;
    double d = 3.14;
    double result = i + d;  // int 被隐式转换为 double

    printf("%f\n", result); // 输出 13.140000
    return 0;
}

在这个例子中,整数 i 在与双精度浮点数 d 相加时自动被转换成 double 类型,以确保运算的精度。

示例 2: 逻辑表达式中的隐式转换

#include <stdio.h>

int main() {
    int a = 0;
    double pi = 3.14;

    if (pi) {
        printf("pi is true\n"); // 输出 "pi is true"
    }
    if (a) {
        printf("a is true\n");
    }
    return 0;
}

在这个例子中,double 类型的 pi 被隐式转换为 bool 类型(true),因为在 C 中任何非零值都被认为是真。相反,a 为 0(假),因此其对应的代码块不执行。

12.3 显式类型转换

显式类型转换是程序员明确指示编译器进行特定类型转换的操作。这通常通过使用类型转换运算符来实现。

示例 1: 使用强制类型转换运算符

#include <stdio.h>

int main() {
    double d = 3.14;
    int i = (int)d;  // 显式地将 double 转换为 int

    printf("%d\n", i); // 输出 3,小数部分被丢弃
    return 0;
}

这里使用了强制类型转换 (int) 显式地将 double 类型的 d 转换为 int 类型,丢弃了小数部分。

示例 2: 显式转换改变表达式结果

#include <stdio.h>

int main() {
    int total_bytes = 1025;
    int size = 512;
    double n_blocks = (double)total_bytes / size;

    printf("%f\n", n_blocks); // 输出 2.001953
    return 0;
}

在这个例子中,如果没有 (double) 强制转换,total_bytes / size 将执行整数除法,结果为 2。通过显式转换 total_bytes 到 double,我们保证了进行的是浮点除法,这样可以得到更精确的结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TENET-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值