C语言类型转换 #

一、类型转换概述 #

1.1 为什么需要类型转换 #

在C语言中,不同类型的数据进行运算时,需要转换为相同类型:

c
int a = 10;
float b = 3.14;
float c = a + b;

1.2 类型转换分类 #

text
类型转换
├── 隐式转换(自动转换)
│   ├── 整数提升
│   ├── 算术转换
│   └── 赋值转换
└── 显式转换(强制转换)
    └── (type)value

二、隐式转换 #

2.1 赋值转换 #

将值赋给不同类型的变量时自动转换:

c
int a = 10;
float b = a;
double c = b;

转换规则:

  • 小类型 → 大类型:安全
  • 大类型 → 小类型:可能丢失数据
c
double d = 3.14159;
int a = d;
printf("%d\n", a);

2.2 整数提升 #

小于int的整数类型自动提升为int:

c
char a = 10;
char b = 20;
int c = a + b;
c
#include <stdio.h>

int main() {
    char a = 127;
    char b = 1;
    int c = a + b;
    printf("char运算结果: %d\n", c);
    return 0;
}

输出:

text
char运算结果: 128

2.3 算术转换 #

不同类型运算时,自动转换为较大类型:

text
long double
    ↑
double
    ↑
float
    ↑
unsigned long long
    ↑
long long
    ↑
unsigned long
    ↑
long
    ↑
unsigned int
    ↑
int

示例:

c
#include <stdio.h>

int main() {
    int a = 5;
    float b = 2.0f;
    
    printf("int / int = %d\n", 5 / 2);
    printf("int / float = %f\n", a / b);
    printf("float / int = %f\n", b / a);
    return 0;
}

输出:

text
int / int = 2
int / float = 2.500000
float / int = 0.400000

2.4 有符号与无符号 #

有符号与无符号运算时,转换为无符号:

c
#include <stdio.h>

int main() {
    int a = -5;
    unsigned int b = 10;
    
    if (a < b) {
        printf("a < b\n");
    } else {
        printf("a >= b\n");
    }
    return 0;
}

输出:

text
a >= b

原因:a被转换为无符号数,变成很大的正数。

2.5 隐式转换示例 #

c
#include <stdio.h>

int main() {
    char c = 'A';
    short s = 100;
    int i = 1000;
    long l = 100000L;
    float f = 3.14f;
    double d = 3.14159;
    
    printf("char + int: %d\n", c + i);
    printf("short * float: %f\n", s * f);
    printf("int / double: %f\n", i / d);
    printf("long + double: %f\n", l + d);
    return 0;
}

三、显式转换 #

3.1 强制类型转换语法 #

c
(type) expression

3.2 基本用法 #

浮点转整数:

c
double d = 3.14159;
int a = (int)d;
printf("%d\n", a);

整数转浮点:

c
int a = 10;
int b = 4;
double c = (double)a / b;
printf("%f\n", c);

指针类型转换:

c
int a = 0x12345678;
char* p = (char*)&a;
printf("%x\n", *p);

3.3 指针转换 #

c
#include <stdio.h>

int main() {
    int a = 65;
    int* pi = &a;
    char* pc = (char*)pi;
    
    printf("整数: %d\n", *pi);
    printf("字符: %c\n", *pc);
    return 0;
}

3.4 void指针 #

c
#include <stdio.h>

void print_value(void* ptr, int type) {
    if (type == 0) {
        printf("int: %d\n", *(int*)ptr);
    } else if (type == 1) {
        printf("float: %f\n", *(float*)ptr);
    } else if (type == 2) {
        printf("char: %c\n", *(char*)ptr);
    }
}

int main() {
    int a = 10;
    float b = 3.14f;
    char c = 'A';
    
    print_value(&a, 0);
    print_value(&b, 1);
    print_value(&c, 2);
    return 0;
}

四、转换风险 #

4.1 精度丢失 #

c
#include <stdio.h>

int main() {
    double d = 3.14159265358979;
    float f = (float)d;
    int a = (int)d;
    
    printf("double: %.15f\n", d);
    printf("float: %.15f\n", f);
    printf("int: %d\n", a);
    return 0;
}

输出:

text
double: 3.141592653589790
float: 3.141592741012573
int: 3

4.2 数据溢出 #

c
#include <stdio.h>

int main() {
    long big = 3000000000L;
    int small = (int)big;
    
    printf("long: %ld\n", big);
    printf("int: %d\n", small);
    return 0;
}

输出:

text
long: 3000000000
int: -1294967296

4.3 符号问题 #

c
#include <stdio.h>

int main() {
    int a = -1;
    unsigned int b = (unsigned int)a;
    
    printf("int: %d\n", a);
    printf("unsigned: %u\n", b);
    return 0;
}

输出:

text
int: -1
unsigned: 4294967295

4.4 指针转换风险 #

c
#include <stdio.h>

int main() {
    double d = 3.14;
    int* p = (int*)&d;
    
    printf("double: %f\n", d);
    printf("int*: %d\n", *p);
    return 0;
}

可能导致未定义行为。

五、安全转换 #

5.1 检查范围 #

c
#include <stdio.h>
#include <limits.h>

int safe_double_to_int(double d) {
    if (d > INT_MAX || d < INT_MIN) {
        printf("警告: 数值超出int范围\n");
        return 0;
    }
    return (int)d;
}

int main() {
    double d1 = 123.45;
    double d2 = 3e10;
    
    printf("d1: %d\n", safe_double_to_int(d1));
    printf("d2: %d\n", safe_double_to_int(d2));
    return 0;
}

5.2 使用安全函数 #

c
#include <stdio.h>
#include <stdlib.h>

int main() {
    const char* str = "12345";
    long num = strtol(str, NULL, 10);
    printf("转换结果: %ld\n", num);
    return 0;
}

5.3 使用固定宽度类型 #

c
#include <stdio.h>
#include <stdint.h>

int main() {
    int32_t a = 100;
    int64_t b = 10000000000LL;
    
    printf("int32_t: %d\n", a);
    printf("int64_t: %lld\n", b);
    return 0;
}

六、常见转换场景 #

6.1 字符串转数字 #

c
#include <stdio.h>
#include <stdlib.h>

int main() {
    const char* str1 = "12345";
    const char* str2 = "3.14";
    
    int i = atoi(str1);
    long l = atol(str1);
    double d = atof(str2);
    
    printf("int: %d\n", i);
    printf("long: %ld\n", l);
    printf("double: %f\n", d);
    return 0;
}

6.2 数字转字符串 #

c
#include <stdio.h>

int main() {
    char buf[100];
    int num = 12345;
    
    sprintf(buf, "%d", num);
    printf("字符串: %s\n", buf);
    return 0;
}

6.3 大小端转换 #

c
#include <stdio.h>
#include <stdint.h>

uint32_t swap_endian(uint32_t value) {
    return ((value & 0xFF000000) >> 24) |
           ((value & 0x00FF0000) >> 8)  |
           ((value & 0x0000FF00) << 8)  |
           ((value & 0x000000FF) << 24);
}

int main() {
    uint32_t num = 0x12345678;
    printf("原值: 0x%08X\n", num);
    printf("转换: 0x%08X\n", swap_endian(num));
    return 0;
}

七、类型转换最佳实践 #

7.1 避免不必要的转换 #

c
int a = 10;
int b = 3;
double c = (double)a / b;

7.2 使用显式转换 #

c
int a = 10;
int b = 4;
double c = a / (double)b;

7.3 注意有符号无符号混用 #

c
int a = -1;
unsigned int b = 1;

if ((unsigned int)a < b) {
    printf("正确比较\n");
}

7.4 检查转换结果 #

c
#include <stdio.h>
#include <limits.h>

int main() {
    long big = 3000000000L;
    
    if (big > INT_MAX || big < INT_MIN) {
        printf("数值超出int范围\n");
    } else {
        int small = (int)big;
        printf("转换结果: %d\n", small);
    }
    return 0;
}

八、总结 #

隐式转换规则 #

情况 转换方向
赋值 值 → 变量类型
运算 小类型 → 大类型
有符号/无符号 有符号 → 无符号

显式转换语法 #

c
(type) expression

转换风险 #

风险 说明
精度丢失 浮点转整数
数据溢出 大类型转小类型
符号错误 有符号转无符号

最佳实践 #

  • 优先使用显式转换
  • 注意有符号/无符号混用
  • 检查转换范围
  • 使用固定宽度类型

下一步,让我们学习存储类!

最后更新:2026-03-26