【问题标题】:Why is "unsigned int ui = {-1};" a narrowing conversion error?为什么是“unsigned int ui = {-1};”缩小转换错误?
【发布时间】:2013-07-07 06:11:21
【问题描述】:

第 8.5.4/7 节的标准解释了缩小转换是什么:

窄化转换是隐式转换

——从浮点类型到整数类型,或者

——从 long double 到 double 或 float,或从 double 到 float,除非源是常量 表达式和转换后的实际值在可以表示的数值范围内 (即使不能准确表示),或

——从整数类型或无作用域枚举类型到浮点类型,除非源 是一个常量表达式,转换后的实际值将适合目标类型并且将 转换回原始类型时产生原始值,或

——从整数类型或无作用域枚举类型到不能代表所有的整数类型 原始类型的值,除非源是常量表达式并且后面的实际值 转换将适合目标类型,并在转换回 原始类型。

然后它在某些列表初始化上下文中禁止此类转换,给出 例子:

[ 注意:如上所述,列表初始化中的顶层不允许进行此类转换。 - 结尾 注意] [示例:

int x = 999;        // x is not a constant expression
const int y = 999;
const int z = 99;
char c1 = x;    // OK, though it might narrow (in this case, it does narrow)
char c2{x};     // error: might narrow
char c3{y};     // error: narrows (assuming char is 8 bits)
char c4{z};     // OK: no narrowing needed
unsigned char uc1 = {5};    // OK: no narrowing needed
unsigned char uc2 = {-1};   // error: narrows
unsigned int ui1 = {-1};    // error: narrows
signed int si1 =
{ (unsigned int)-1 };   // error: narrows
int ii = {2.0};         // error: narrows
float f1 { x };         // error: might narrow
float f2 { 7 };         // OK: 7 can be exactly represented as a float
int f(int);
int a[] =
{ 2, f(2), f(2.0) }; // OK: the double-to-int conversion is not at the top level

—结束示例]

示例说明的所有 7 个错误均由以下人员报告 clang 3.2/3.3 与-std=c++11,例如

error: non-constant-expression cannot be narrowed from type 'int' to 'char' in initializer list [-Wc++11-narrowing]

gcc 4.7.2/4.8.1 均未将它们报告为错误,但在每种情况下 给出了类似的警告,例如

warning: narrowing conversion of ‘x’ from ‘int’ to ‘char’ inside { } [-Wnarrowing]

(所以 gcc 似乎知道合规要求,但选择容忍不合规 默认情况下。)

我不明白的例子是:

unsigned int ui1 = {-1};    // error: narrows

可以作为一个例子。 (对称的si1 示例也是如此。)显然 它可能作为例子的唯一词是第四个词 以及上面给出的窄化转换定义中的最后一项;但 如果是这样,那么为什么该示例不能通过限定符逃脱 除了源是常量表达式和后面的实际值 转换将适合目标类型,并在转换回 原始类型?当然-1 有一个整数常量,如果转换为unsigned 并返回, 仍然产生int -1

我错过了什么?

【问题讨论】:

    标签: c++ c++11 type-conversion language-lawyer narrowing


    【解决方案1】:

    -1 肯定有一个整数常量,如果转换为无符号并返回,仍然会产生 int -1?

    这是错误的。如果将 -1 转换为 unsigned,则会得到 UINT_MAX。这很好,因为总是定义转换为无符号类型。但是,UINT_MAX 不适合 int,并且只有当值适合目标类型时,标准才会定义到有符号类型的转换。

    【讨论】:

    • 具体来说,这种转换会产生实现定义的结果。将UINT_MAX 转换为int通常会产生-1,但不能保证。
    • @R.MartinhoFernandes “UINT_MAX 不适合 int”是否意味着“UINT_MAX 可以使用比 int 更多的位”?
    • @MikeKinghan。不,这意味着UINT_MAX 超出了int 可表示的值范围。
    • 但是,当我查看最新的草稿时,我不再看到反向转换检查。这让我觉得 unsigned i = { -1 }; 是有效的 C++14 代码。
    • @JohannesSchaub-litb N3690 中的示例 - 是的,示例是非规范性的,但是 - 仍然有 unsigned int ui1 = {-1}; // error: narrows
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-02
    • 2021-08-07
    • 2020-06-20
    • 1970-01-01
    • 1970-01-01
    • 2010-12-24
    相关资源
    最近更新 更多