【问题标题】:Narrowing Conversion of unsigned int to short unsigned intunsigned int 到 short unsigned int 的窄化转换
【发布时间】:2013-09-03 23:42:42
【问题描述】:

警告:在 C++11 [-Wnarrowing]

我无法弄清楚为什么我从 MinGW 编译以下代码时收到此警告:

unsigned stride = 3;

D3DVERTEXELEMENT9 NORMALELEMENT =
{ 0, stride * sizeof(gs_scalar), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 };
if (useNormals) stride += 3;

它抱怨那些大括号内的stride * sizeof(gs_scalar)(gs_scalar 是float),但我看不出这是一个缩小转换,因为sizeof 返回字节数。我尝试将 stride 的数据类型更改为 WORD、DWORD、CHAR 等所有类型,但我不断收到相同或类似的警告。

【问题讨论】:

  • 使用大括号初始化可以防止在 c++11 中缩小转换。如果这是您的意图,您是否尝试过将 stride * sizeof(gs_scalar) 包含在显式转换中?
  • 这是 C++11 中的错误,不是警告...

标签: c++ c++11


【解决方案1】:

D3DVERTEXELEMENT9的定义:

struct D3DVERTEXELEMENT9 {
  WORD Stream;
  WORD Offset;
  BYTE Type;
  BYTE Method;
  BYTE Usage;
  BYTE UsageIndex;
};

(来自http://msdn.microsoft.com/en-us/library/windows/desktop/bb172630%28v=vs.85%29.aspx,但删除了 typedef 的东西)。

因此,您正在使用 stride * sizeof(gs_scalar) 初始化 NORMALELEMENT.Offset

sizeof(gs_scalar) 的类型是std::size_t,在你的平台上显然是unsigned intstride 的类型是unsigned(即unsigned int),所以stride * sizeof(gs_scalar) 的类型是@ 987654333@。但是NORMALELEMENT.Offset 的类型是WORD,即unsigned short

我猜在你的平台上unsigned int 是 32 位宽,但 unsigned short 只有 16 位宽,所以这确实是一个缩小转换(如果 stride * sizeof(gs_scalar) 的值不适合 16 位你'会丢失数据)。

即使将stride定义为WORD,在与sizeof(gs_scalar)相乘的过程中也会提升为unsigned int,所以情况保持不变。

如果您确定 stride * sizeof(gs_scalar) 永远不会超过 USHRT_MAX(即对您而言 216−1 即 65535),这似乎很可能(在示例中为 3 * 4即 12),那么您可以使用演员表(如特洛伊在 cmets 中所说),例如static_cast<WORD>(stride * sizeof(gs_scalar)).

【讨论】:

    【解决方案2】:

    strideunsigned,因此它的值可能太大而无法放入 unsigned short。此外,sizeof 的类型 std::size_t 也大于 WORD

    如果您将stride 设为const unsigned,则编译器可以看到12 的实际值确实适合unsigned short,并且错误消失了。但如果它不是常量,则需要明确保证计算适合,因为大括号内的初始化程序不允许截断或溢出。 (“Narrowing”是指丢失数据,暗指将数字一端的数字切掉。)

    只需使用static_cast< WORD >( … )

    【讨论】:

    • 感谢您解决了警告!太棒了,你们俩。
    • const 的那件事很有趣。
    • @user2734025 如果有帮助请点赞,如果解决了问题,请点击复选标记。感谢您提出的措辞恰当的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-19
    • 2012-07-11
    • 1970-01-01
    • 2015-01-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多