Reputation: 93
I need integer types of specific widths in C++, but I am not sure what type to use: int
, long
, etc. I realize I could use sizeof
to find the size of each different integer type, but int
, long
and long long
are not platform independent. This task would also be way too tedious.
Is there any way to specifiy an integer type of a specific size (such as a 32-bit or 64-bit integer) in C++? How would I go about doing this?
Upvotes: 0
Views: 1129
Reputation: 1935
I think what you're looking for is fixed width integer types. These are defined in the header <cstdint>
.
For your purposes, you could stick with int[xx]_t
, where you replace [xx]
with the width of the integer type you need, in bits. uint[xx]_t
does something similar, with unsigned integer types.
You could, for example, use int8_t
, int16_t
, uint8_t
, uint_16t
, etc.
Upvotes: 7
Reputation: 9852
If you need to work out the type at compile time from a constexpr number of bits you can do:
#include <type_traits>
#include <iostream>
template <int NumBits, typename=void>
struct uint_selector;
template <int NumBits>
struct uint_selector<NumBits, std::enable_if_t< 0 <= NumBits && NumBits <= 8>>
{
typedef uint8_t int_type;
};
template <int NumBits>
struct uint_selector<NumBits, std::enable_if_t<8 < NumBits && NumBits <= 16 >>
{
typedef uint16_t int_type;
};
template <int NumBits>
struct uint_selector<NumBits, std::enable_if_t<16 < NumBits && NumBits <= 32 >>
{
typedef uint32_t int_type;
};
template <int NumBits>
struct uint_selector<NumBits, std::enable_if_t<32 < NumBits && NumBits <= 64 >>
{
typedef uint64_t int_type;
};
// Then use as:
int main()
{
// my_val will be the smallest standard type which is big enough type to hold 15 bits (e.g. a uint16_t)
uint_selector<15>::int_type my_val = 5;
}
Upvotes: 3
Reputation: 7873
You can use template
specialization of a type trait, provided you know the sizes at compile time.
#include <cstdint>
#include <type_traits>
template <std::size_t SIZE>
struct num_selector;
template<>
struct num_selector<sizeof(short)> {
using type = short;
};
template<>
struct num_selector<sizeof(int)> {
using type = int;
};
template <std::size_t SIZE>
using num_selector_t = typename num_selector<SIZE>::type;
int main() {
std::uint8_t shortish[sizeof(short)];
std::uint8_t intish[sizeof(int)];
static_assert(std::is_same_v<num_selector_t<sizeof(shortish)>, short>);
static_assert(std::is_same_v<num_selector_t<sizeof(intish)>, int>);
return 0;
}
This make some assumptions that short
and int
are different sizes, but that's reasonable on most platforms (and can be checked via static_assert
if you're concerned).
If you don't know how many bytes you're going to read until you're actually reading them (e.g., some end of field marker), you're better off picking the largest type you could ever need and just dealing with that.
Upvotes: 0