【问题标题】:How to define uint64_t constant?如何定义 uint64_t 常量?
【发布时间】:2018-07-21 05:50:47
【问题描述】:

我的 C++ 程序中有 uint64_t 常量(QtCreator 4.6.1 中的 clang 6.0.1)。

例如:

uint64_t a = 0xffffffffffffffffULL;

问题是,我在 IDE 中收到以下警告:

Warning: implicit conversion from 'unsigned long long' to 'uint64_t' (aka 'unsigned long')

我也尝试将其更改为以下内容但没有成功:

uint64_t a = UINT64_C(0xffffffffffffffff);
uint64_t a = 0xffffffffffffffffUL;

我可以选择使用 C++14 标准和选项进行计算:-Wconstant-conversion

检查类型大小:

std::cout << "uint64_t " << sizeof (uint64_t) << std::endl; 
std::cout << "unsigned long " << sizeof (unsigned long) << std::endl;
std::cout << "unsigned long long " << sizeof (unsigned long long) << std::endl;

结果:

uint64_t 8  
unsigned long 8
unsigned long long 8

知道如何解决这个问题以及为什么 IDE 认为正在发生大小转换?

编辑:我刚刚检查了宏扩展:

define UINT64_C(c)  c ## UL

这意味着提供的示例应该可以工作,但它不能:

uint64_t a = 0xffffffffffffffffUL;

【问题讨论】:

  • 答案在您的警告信息中!请仔细阅读。
  • 可能相关:question 1, question 2
  • @Someprogrammerdude - 是的,我试过了。用示例更新了问题。不,答案不在警告中。
  • @Ross 如果您的编译器将0xffffffffffffffffUL 视为unsigned long long 常量(因为您说错误仍然显示“从'unsigned long long' 转换”),那么您的unsigned long 类型不会' t 有 64 位。如果您的标头仍然将uint64_t 定义为unsigned long,那么就大错特错了。您是否不小心使用了另一个平台的标题?但是,这与测试程序的输出不匹配。
  • @hvd 这似乎确实是混合标头的问题。我试图将定义复制到另一个文件中,但警告未显示在其中。

标签: c++ c++14 qt-creator


【解决方案1】:

unsigned long long 至少为 64 位,因此它可能是比uint64_t 更大的类型

我会写(注意使用 constexpr,因为它是一个常量):

#include <cinttypes>
#include <limits>
constexpr auto a = std::numeric_limits<std::uint64_t>::max();

要以可移植的方式定义一个非最大值 uint64_t 常量,只需删除末尾的 ULL 部分:

constexpr std::uint64_t b = 0x12345;

【讨论】:

  • 相等或更大。 64 位,而不是字节。取决于数据模型:en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models。如何以可移植的方式定义非最大常量?
  • @bit_data_models 很好地捕获字节 -> 位。相等或更大是什么意思?我在回答中说“至少”,这与相等或更大相同。没有?
【解决方案2】:

感谢@hvd 评论,此警告已得到解决。

检查了所有包含的头文件。出于某种原因,stdint.hcstdint 都被包括在内。我只留下了cstdint。它们可能来自不同的平台,有不同的定义。

工作示例:

uint64_t v0 = UINT64_C(0x736f6d6570736575);

【讨论】:

  • 宏是邪恶的 - 几乎不需要。
  • 如果只包含stdint.h 会怎样?或者如果只有cstdint?据推测,对于其中一种情况,您会收到相同的虚假警告(如果两者都包括在内,这应该不是问题)。 “他们可能来自不同的平台,有不同的定义。”:这意味着你的安装不正确。
【解决方案3】:

这是一种方法:

auto a = static_cast<uint64_t>(-1);

【讨论】:

    【解决方案4】:

    编译器警告您在 C++ 中不保证具有相同大小的类型之间的 隐式 转换。一种可能的解决方法是使其明确:

    uint64_t a = static_cast<uint64_t>(0xffffffffffffffffULL);
    

    【讨论】:

      【解决方案5】:

      这里首先要注意的是,您不需要LL 后缀。

      一个整数文字会自动拥有一个可以容纳数字的类型。查看this 表以了解确切类型。此规则的唯一例外是,如果您指定仅适合 unsigned long long int 的十进制文字。然后需要指定u后缀。

      现在,可以通过强制转换轻松删除警告:

      uint64_t a = (uint64_t)0xffffffffffffffff;

      或者如果你不喜欢 C 转换,那么使用 static_cast:

      uint64_t a = static_cast&lt;uint64_t&gt;(0xffffffffffffffff);


      到目前为止,这是理论,但是您的编译器/安装存在一些问题。如果您对此有隐式转换警告:

      uint64_t a = 0xffffffffffffffffUL;

      其中uint64_tunsigned long,那么这意味着0xffffffffffffffffUL 实际上变成了unsigned long long int。但它不应该是,因为sizeof(unsigned long) 已经是 8 了。如果编译器和安装正确,这显然是不可能的情况。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-02-18
        • 2016-07-23
        • 2014-10-07
        • 1970-01-01
        • 2016-07-14
        • 2023-04-01
        • 2011-02-12
        • 1970-01-01
        相关资源
        最近更新 更多