2

警告:在 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 is float) ,但我不明白这是如何缩小转换,因为sizeof返回字节数。我尝试将stride的数据类型更改为 WORD、DWORD、CHAR 等所有内容,但我不断收到相同或类似的警告。

4

2 回答 2

4

看看 的定义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)is的类型std::size_t显然unsigned int在您的平台上,而 of 的类型strideunsigned(ie unsigned int),所以 of 的类型stride * sizeof(gs_scalar)unsigned int。但类型NORMALELEMENT.OffsetWORDwhich is unsigned short

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

即使你定义stride为 a ,它在与 的乘法中WORD也被提升为,所以情况保持不变。unsigned intsizeof(gs_scalar)

如果您确定它stride * sizeof(gs_scalar)永远不会超过USHRT_MAX(即对您而言 2 16 -1 即 65535),这似乎很可能(在示例中为 3 * 4 即 12),那么您可以使用强制转换(如 Troy 在评论),例如static_cast<WORD>(stride * sizeof(gs_scalar))

于 2013-08-31T09:44:15.113 回答
2

stride所以unsigned它的值可能太大而无法放入unsigned short. 此外sizeof还有类型std::size_t也大于WORD

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

只需使用static_cast< WORD >( … ).

于 2013-08-31T09:42:33.963 回答