C++隐式数字类型降级

Ale*_*xei 1 c++ types casting c++14

最近,我注意到C/C++似乎是非常允许的数字类型转换,因为它隐式地将一个double转换为int.

测试:

环境:cpp.sh,Standard C++ 14,Compilation warnings all set

码:

int intForcingFunc(double d) {
    return d;                       // this is allowed
}

int main() {
    double d = 3.1415;
    double result = intForcingFunc(d);
    printf("intForcingFunc result = %f\n", result);

    int localRes = d;               // this is allowed
    printf("Local result = %d\n", localRes);

    int staticCastRes = static_cast<int>(d);                // also allowed
    printf("Static cast result = %d\n", staticCastRes);
}
Run Code Online (Sandbox Code Playgroud)

编译期间没有警告问题.

文档提到切向主题,但错过了问题的确切情况:

C++是一种强类型语言.许多转换,特别是那些暗示对值的不同解释的转换,需要显式转换,在C++中称为类型转换.

我也尝试过托管语言(C#),并且不允许所有这些情况(如预期的那样):

static int intForcingFunc(double d)
{
    // Not legal: Cannot implicitly convert type 'double' to 'int'
    // return d;
    return Convert.ToInt32(d);
}

static void Main(string[] args)
{
    double d = 3.1415;
    double result = intForcingFunc(d);
    Console.WriteLine("intForcingFunc result = " + result);

    // Not legal: Cannot implicitly convert type 'double' to 'int'
    // int localRes = d;
    int localRes = (int)d;
    Console.WriteLine("local result = " + result);

    Console.ReadLine();
}
Run Code Online (Sandbox Code Playgroud)

为什么这种行为允许使用强类型语言?在大多数情况下,这是不希望的行为.这背后的一个原因似乎是缺乏算术溢出检测.

eml*_*lai 6

不幸的是,这种行为是从C继承的,C在这些事情中臭名昭着"信任程序员".

隐式浮点数到整数转换的确切警告标志是-Wfloat-conversion,也是由-Wconversion.对于一些未知的原因,-Wall,-Wextra,和-pedantic(其中cpp.sh提供)不包括这些标志.

如果你使用Clang,你可以给它-Weverything启用字面上的所有警告.如果您使用GCC,则必须明确启用-Wfloat-conversion-Wconversion在执行此类转换时收到警告(以及您希望启用的其他有用标记).

如果需要,可以将其变为例如错误-Werror-conversion.


C++ 11甚至引入了一种全新的更安全的初始化语法,称为统一初始化,您可以使用它来获取示例中隐式转换的警告,而不启用任何编译器警告:

int intForcingFunc(double d) {
    return {d};  // warning: narrowing conversion of 'd' from 'double' to 'int' inside { }
}

int main() {
    double d{3.1415};  // allowed
    int localRes{d};  // warning: narrowing conversion of 'd' from 'double' to 'int' inside { }
}
Run Code Online (Sandbox Code Playgroud)