C ++隐式数值类型降级 [英] C++ implicit numeric type demoting

查看:166
本文介绍了C ++隐式数值类型降级的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



测试:



环境: cpp.sh Standard C ++ 14 编译警告全部设置



代码:

  int intForcingFunc(double d){
return d; //这是允许的
}

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

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

int staticCastRes = static_cast< int>(d); //也允许
printf(Static cast result =%d\\\
,staticCastRes);
}

编译期间无警告问题。



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


C ++是一种强类型语言。许多转换,特别是那些意味着对值的不同解释的转换,需要一个明确的转换,在C ++中称为类型转换。


我也试过一个托管语言(C#),所有这些情况是不允许的(如预期):

  static int intForcingFunc(double d)
{
//不合法:不能隐式地将类型'double'转换为'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);

//不合法:不能隐式地将类型'double'转换为'int'
// int localRes = d;
int localRes =(int)d;
Console.WriteLine(local result =+ result);

Console.ReadLine();
}

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

解决方案

不幸的是,这种行为是从C继承而来的,在这些东西中,信任程序员

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



如果你使用Clang,你可以给它 -Weverything 启用字面上所有的警告。如果您使用GCC,则必须明确启用 -Wfloat-conversion -Wconversion 才能在执行此类转换时收到警告(除了其他有用的标志,你将要启用)。



如果你想,你可以把它转换为一个错误与eg -Werror-conversion






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

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

int main(){
double d {3.1415} // allowed
int localRes {d}; // warning:narrowing'd'from'double'to'int'inside {}
}


Recently, I have noticed that C/C++ seems to be very permissible with numeric type conversion, as it implicitly casts a double to int.

Test:

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

Code:

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);
}

No warnings are issues during compilation.

Documentation mentions tangentially the subject, but misses the exact case of the question:

C++ is a strong-typed language. Many conversions, specially those that imply a different interpretation of the value, require an explicit conversion, known in C++ as type-casting.

I have also tried in a managed language (C#) and all these cases are not allowed (as expected):

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();
}

Why is this behavior allowed in a strong-typed language? In most cases, this is undesired behavior. One reason behind this seems to be lack of arithmetic overflow detection.

解决方案

Unfortunately, this behavior is inherited from C, which notoriously "trusts the programmer" in these things.

The exact warning flag for implicit floating-point to integer conversions is -Wfloat-conversion, which is also enabled by -Wconversion. For some unknown reason, -Wall, -Wextra, and -pedantic (which cpp.sh provides) don't include these flags.

If you use Clang, you can give it -Weverything to enable literally all warnings. If you use GCC, you must explicitly enable -Wfloat-conversion or -Wconversion to get a warning when doing such conversions (among other useful flags you will want to enable).

If you want, you can turn it to an error with e.g. -Werror-conversion.


C++11 even introduced a whole new safer initialization syntax, known as uniform initialization, which you can use to get warnings for the implicit conversions in your example without enabling any compiler warnings:

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 { }
}

这篇关于C ++隐式数值类型降级的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆