缩小unsigned int到short unsigned int的转换

时间:2013-08-31 09:21:46

标签: c++ c++11

  

警告:缩小{(stride * 4u)'从'unsigned int'转换为'WORD {aka short unsigned int}'{}内部的格式错误在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,所有内容,但我仍然收到相同或类似的警告。

2 个答案:

答案 0 :(得分:3)

查看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内容。)

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

sizeof(gs_scalar)的类型为std::size_t,在您的平台上显然为unsigned intstride的类型为unsigned(即{{1} }),因此unsigned int的类型为stride * sizeof(gs_scalar)。但unsigned int的类型为NORMALELEMENT.Offset WORD

我想你的平台unsigned short是32位宽,unsigned int只有16位宽,所以这确实是一个缩小的转换(如果unsigned short的值可以' t适合16位,你会丢失数据。)

即使您将stride * sizeof(gs_scalar)定义为stride,也会在WORD的乘法中将其提升为unsigned int,因此情况保持不变。

如果您确定sizeof(gs_scalar)永远不会超过stride * sizeof(gs_scalar)(即2 16 -1,即65535),这似乎很可能(在示例中)它是3 * 4即12),那么你可以使用演员(如评论中的特洛伊所说),例如USHRT_MAX

答案 1 :(得分:2)

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

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

只需使用static_cast< WORD >( … )