简体   繁体   中英

How to define uint64_t constant?

I have the uint64_t constants in my C++ program (clang 6.0.1 in QtCreator 4.6.1).

For example:

uint64_t a = 0xffffffffffffffffULL;

The problem is, that I get the following warning in the IDE:

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

I tried also to change it to the following without success :

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

I have options to compute with C++14 standard and option: -Wconstant-conversion

Checking the types size:

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;

Result:

uint64_t 8  
unsigned long 8
unsigned long long 8

Any idea how to fix this and why IDE thinks that size conversion is happening?

Edit: I just checked the macro expansion:

define UINT64_C(c)  c ## UL

This means that provided example should work, however it doesn't:

uint64_t a = 0xffffffffffffffffUL;

unsigned long long is at least 64 bits, so it could be a bigger type than uint64_t

I would write (note the use of constexpr because it's a constant):

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

And to define a non-max uint64_t constant in portable way, just remove the ULL part at the end:

constexpr std::uint64_t b = 0x12345;

This warning is resolved thanks to @hvd comment.

Checked all included header files. For some reason, both stdint.h and cstdint were included. I left only the cstdint . They are probably from different platforms and have different definitions.

The working example:

uint64_t v0 = UINT64_C(0x736f6d6570736575);

The compiler is warning you of an implicit conversion between types that are not guaranteed to be of the same size in C++. A possible fix is to make it explicit:

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

这是一种方法:

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

The first thing to note here is that you don't need the LL suffix.

An integer literal automatically will have a type which can hold the number. Check out this table for exact types. The only exception to this rule is if you specify a decimal literal which only fits to unsigned long long int . Then you need to specify the u suffix.

Now, the warning can be removed easily with a cast:

uint64_t a = (uint64_t)0xffffffffffffffff;

or if you don't like C cast, then with static_cast :

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


So far, this was the theory, but you have some problems with your compiler/installation. If you have the implicit conversion warning for this:

uint64_t a = 0xffffffffffffffffUL;

where uint64_t is unsigned long , then it means that 0xffffffffffffffffUL actually becomes unsigned long long int . But it should not be, as sizeof(unsigned long) is 8 already. This is clearly an impossible situation, if the compiler and installation is correct.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM