【问题标题】:error: narrowing conversion of ‘18446744069414584320ull’ from ‘long long unsigned int’ to ‘int’ inside { } [-Wnarrowing]错误:缩小“18446744069414584320ull”从“long long unsigned int”到“int”的转换{} [-Wnarrowing]
【发布时间】:2019-04-17 19:08:32
【问题描述】:

这段代码有什么问题?我正在使用 GCC 6.3。

https://ideone.com/ektGEp

a.cpp:在函数“int main()”中:`a.cpp:26:24:错误:将“18446744069414584320ull”从“long long unsigned int”缩小到“int”在{} [-Wnarrowing ]

#include <iostream>
using namespace std;
#include <smmintrin.h>
#include <emmintrin.h>
#include <tmmintrin.h>

typedef union {
        __m64  mm64[2];
        __m128 mm128i;
} sse2_t;

#define const_epi32( i3,i2,i1,i0 )      \
            { static_cast<unsigned long long> (static_cast<unsigned long long>(i1) << 32), \
              static_cast<unsigned long long> (static_cast<unsigned long long>(i3) << 32) }

int main() {

        sse2_t arr_val[3] = { const_epi32(0,-1,0,-1),
                          const_epi32(0, 0,-1, -1),
                          const_epi32(0, 0,0, 1024) 
                        }; //error!

        sse2_t val = const_epi32(0,-1,0,-1); // ok!
        // your code goes here
        return 0;
}

【问题讨论】:

  • 根据错误消息,它正在尝试使用unsigned long long 类型的值初始化int 类型的对象,而int 太小了。

标签: c++


【解决方案1】:

__m64__m128 类型非常特殊,代表向量寄存器,这意味着您不能以通常的方式为它们分配值(就像您在代码中尝试做的那样)。您需要使用特殊的加载函数将数据放入寄存器,并使用特殊的存储函数从那里取回数据。

这是一个如何将数据(四个浮点数)加载到__m128 变量中的示例:

#include <cstring>
#include <smmintrin.h>
int main() {
  float f[4];
  memset(f, 0, 16);
  __m128 a = _mm_load_ps(f);
  return 0;
}

这个页面有很多关于可用的所有不同类型和内在函数的信息:https://software.intel.com/sites/landingpage/IntrinsicsGuide/

【讨论】:

  • 是的,你完全正确。你的建议让我想起我们有特殊的负载内在函数。我重写了 const_epi32 宏,如下面的帖子所示。
【解决方案2】:
#define const_epi32( i3,i2,i1,i0 )      \
        { _m_from_int64( (static_cast<unsigned long long>(i1) << 32), \
          _m_from_int64( (static_cast<unsigned long long>(i3) << 32) }

【讨论】:

  • 您的宏有四个输入参数 i3 i2 i1 i0 看起来很奇怪,但它只使用其中两个; i2 和 i0 未使用?
  • 哦。它只是来自真实代码的 sn-p,只是为了定位问题的根本原因:)
【解决方案3】:

const_epi32(0, 0,-1, -1) 部分导致警告,因为您将“0xffffFFFFffffFFFF”分配给正在缩小的 32 位“int”。

我假设其他情况不会引起警告,因为分配的值是常数 0,不会受到变窄的影响。

另一个问题是,为什么__m64int。我假设 __m64 不能直接分配给(作为一个 MM 寄存器),并且缩小检查(至少对于常量分配)在编译器中是虚假的。

【讨论】:

  • 这个int被分配到哪里了?
  • @chris:是的!这是真正的问题! :-) 我假设 __m64 不是编译器的真实类型。它代表一个MM寄存器。
  • @chris:它是 __m64。 GCC 对 __m64 使用 int[2] 的语义。但这不一定是便携的东西。例如,clang 使用 long long[1] 代替。
猜你喜欢
  • 1970-01-01
  • 2016-12-20
  • 1970-01-01
  • 2016-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-27
相关资源
最近更新 更多