C 语言的函数参数在调用时可能会自动进行 默认提升(default argument promotions)。这种提升通常发生在 整数类型 和 浮点类型 之间,特别是对于小类型(如 char 或 short)和 float 类型的参数。C 语言会将较小的类型提升到较大的类型,以确保类型一致性。这些规则主要是为了确保类型兼容性和避免数据丢失。如需要控制数据的类型转换,尤其是在函数调用时,可以显式地转换参数类型,避免依赖默认提升。

1、默认参数提升的规则

在函数调用中,某些类型的实参会根据函数声明时的参数类型进行提升或转换。特别是对于 整数类型,如在函数参数声明中使用 floatdouble,而传入的参数为 int 类型时,参数会被提升为 floatdouble

1)char 和 short 类型提升为 int

在 C 语言中,如果你传递一个 charshort 类型的参数给一个接受 int 类型的函数时,这些较小的整数类型会被提升为 int。这就是所谓的 整数提升。

#include <stdio.h>

void func(int x) {
    printf("%d\n", x);
}

int main() {
    char c = 65;  // ASCII 'A'
    func(c);  // char 会被提升为 int
    return 0;
}

2)float 类型提升为 double

如传递一个 float 类型的参数给一个接受 double 类型的函数,float 会被提升为 double。这种提升发生在所有函数调用的参数传递中,目的是确保精度不丢失。

#include <stdio.h>

void func(double x) {
    printf("%f\n", x);
}

int main() {
    float f = 3.14f;
    func(f);  // float 会被提升为 double
    return 0;
}

3)指针类型没有提升

指针类型(如 char*int*)不会像整数类型那样发生提升。传递给函数的指针参数将直接按照传递时的类型进行处理。

#include <stdio.h>

void func(int* p) {
    printf("%d\n", *p);
}

int main() {
    char c = 'A';
    func(&c);  // 直接传递 char*,没有提升
    return 0;
}

2、函数声明与默认参数提升

C 语言函数调用时的默认提升规则,不仅影响函数参数的传递,还与函数声明的类型匹配有关。编译器会自动将不匹配的类型转换为更大的类型,以避免丢失数据。

#include <stdio.h>

void func(int a, double b) {
    printf("%d %f\n", a, b);
}

int main() {
    short x = 5;  // short 类型
    float y = 3.14f;  // float 类型

    func(x, y);  // x 会被提升为 int,y 会被提升为 double
    return 0;
}

3、提升的原因

C 语言对整数类型的提升规则是为了兼容不同平台的表示方式。charshort 通常使用比 int 小的存储空间,因此它们需要提升为 int,以避免在算术运算中丢失数据。

floatdouble 具有不同的精度,double 具有更高的精度,因此为了防止 floatdouble 之间的精度损失,float 会被自动提升为 double