Every time I write int/float/char I wonder what the hell they actually are.
Is int 32b/64b?
Actually int can be infinite bits as well char.
This is missing from Rust.
So should I write int32_t instead?
C++ type system AKA what is exactly int ?
Moderators: hgm, Rebel, chrisw
-
- Posts: 493
- Joined: Sat Mar 02, 2013 11:31 pm
-
- Posts: 1784
- Joined: Wed Jul 03, 2019 4:42 pm
- Location: Netherlands
- Full name: Marcel Vanthoor
Re: C++ type system AKA what is exactly int ?
If I remember correctly, "int" is defined is either 2 or 4 bytes, depending on the default as set by the architecture.
Rust does not have "int". It uses uX / iX (unsigned / signed, where X is 8, 16, 32, 64 or 128 bits), or usize / isize (signed / unsigned, where "size" means "go as high as you can go on the architecture you're compiling on").
So, I assume if Rust was available for 16 or 128 bit systems, usize would be 16 or 128 bits on those systems.The size of this primitive is how many bytes it takes to reference any location in memory. For example, on a 32 bit target, this is 4 bytes and on a 64 bit target, this is 8 bytes.
-
- Posts: 300
- Joined: Mon Apr 30, 2018 11:51 pm
Re: C++ type system AKA what is exactly int ?
C++ is vague on this; int must be at least as large as short, and no larger than long. In addition, it must be signed, capable of holding [INT_MIN, INT_MAX], and “have the natural size suggested by the architecture of the execution environment”.
On all modern PCs, int is 32 bits. If you code for MS-DOS or very limited microcontrollers, you may find int to be 16 bits. On super-strange old platforms, it might be 18 or 36 bits (I'm honestly not sure). I've never seen a platform where it was 64 bits, but who knows.
On all modern PCs, int is 32 bits. If you code for MS-DOS or very limited microcontrollers, you may find int to be 16 bits. On super-strange old platforms, it might be 18 or 36 bits (I'm honestly not sure). I've never seen a platform where it was 64 bits, but who knows.
-
- Posts: 2495
- Joined: Tue Aug 30, 2016 8:19 pm
- Full name: Rasmus Althoff
Re: C++ type system AKA what is exactly int ?
Depends on your target platform. int is at least 16 bits, but may be more. The only case where int doesn't fit in a CPU register is 8 bit controllers such as small AVRs. char is always 8 bits in practice - technically, it is the smallest addressable memory unit that can hold the basic character set. float is not defined precisely, but in practice, it's 32 bits, and double is 64 bits.
Where it gets really murky is e.g. "long int". That has 32 bit under 32 bit Linux, but 64 bit under 64 bit Linux. Under Windows, it's always 32 bit.
Depends on what you want. For anything that needs a specific memory layout, you use types like int32_t. There are also types like int_least32_t (integer type with at least 32 bits) and int_fast32_t (fastest integer type with at least 32 bits).So should I write int32_t instead?
Rasmus Althoff
https://www.ct800.net
https://www.ct800.net
-
- Posts: 16
- Joined: Sat Dec 12, 2020 5:29 am
- Full name: Ben Bradley
Re: C++ type system AKA what is exactly int ?
This comes from the original K&R C and is the same in C++. int is defined as the width of the processor's accumulator, except the minimum is 16, so on 8-bit processors int is 16 bits. Also, the latest processors are 64 bits, but 64-bit compilers (that I've used) use 32 bit ints. No, I don't know why. I don't recall there being a maximum number of bits for int.
Run this code, it will tell you what's what for your compiler. I'm on Windows 10, 64 bit. For gcc (g++) 10.2.0 (in cygwin, 64 bit), the output is 1 2 4 8 8.
For Embarcadero (formerly Borland) 7.30 (32 bit compiler) the output is 1 2 4 4 8, so a long is eight bytes for one, and 4 bytes for the other.
I use int32_t and such, just so I always know. int8_t and uint8_t are still signed and unsigned char, just like C, so when I want to print one of these as a decimal number, I cast to uint16_t, else it prints the ASCII character of the value.
#include <iostream>
using namespace std;
int main (void)
{
cout << "sizeof (char) " << sizeof (char) << endl;
cout << "sizeof (short) " << sizeof (short) << endl;
cout << "sizeof (int) " << sizeof (int) << endl;
cout << "sizeof (long) " << sizeof (long) << endl;
cout << "sizeof (long long) " << sizeof (long long) << endl;
} // int main (void)
Run this code, it will tell you what's what for your compiler. I'm on Windows 10, 64 bit. For gcc (g++) 10.2.0 (in cygwin, 64 bit), the output is 1 2 4 8 8.
For Embarcadero (formerly Borland) 7.30 (32 bit compiler) the output is 1 2 4 4 8, so a long is eight bytes for one, and 4 bytes for the other.
I use int32_t and such, just so I always know. int8_t and uint8_t are still signed and unsigned char, just like C, so when I want to print one of these as a decimal number, I cast to uint16_t, else it prints the ASCII character of the value.
#include <iostream>
using namespace std;
int main (void)
{
cout << "sizeof (char) " << sizeof (char) << endl;
cout << "sizeof (short) " << sizeof (short) << endl;
cout << "sizeof (int) " << sizeof (int) << endl;
cout << "sizeof (long) " << sizeof (long) << endl;
cout << "sizeof (long long) " << sizeof (long long) << endl;
} // int main (void)
-
- Posts: 16
- Joined: Sat Dec 12, 2020 5:29 am
- Full name: Ben Bradley
Re: C++ type system AKA what is exactly int ?
Here's a longer version of the code that may be useful. Notice long double is 16 bytes for gcc, but 10 bytes on Embarcadero. I'm sure the value only taces 10 bytes in both (the use the same floating point unit on the processor), but gcc pads it to get 16 byte alignment.
// based from "The C++ Standard Library" 1st ed. pp. 64-65
#include <iostream>
#include <limits>
using namespace std;
int main (void)
{
#ifdef __BORLANDC__
cout << "__BORLANDC__ defined as " << __BORLANDC__ << endl;
#else
#ifdef __GNUC__
cout << "__GNUC__ defined as " << __GNUC__ << endl;
#else
cout << "Compiler unknown." << endl;
#endif //#ifdef __GNUC__
#endif //#ifdef __BORLANDC__
cout << "min (uint8_t): " << int(numeric_limits<uint8_t>::min()) << endl;
cout << "max (uint8_t): " << int(numeric_limits<uint8_t>::max()) << endl;
cout << "min (int8_t): " << int(numeric_limits<int8_t>::min()) << endl;
cout << "max (int8_t): " << int(numeric_limits<int8_t>::max()) << endl;
cout << "min (char): " << int(numeric_limits<char>::min()) << endl;
cout << "max (char): " << int(numeric_limits<char>::max()) << endl;
cout << endl;
cout << "min (uint16_t): " << numeric_limits<uint16_t>::min() << endl;
cout << "max (uint16_t): " << numeric_limits<uint16_t>::max() << endl;
cout << "min (int16_t): " << numeric_limits<int16_t>::min() << endl;
cout << "max (int16_t): " << numeric_limits<int16_t>::max() << endl;
cout << "min (short): " << numeric_limits<short>::min() << endl;
cout << "max (short): " << numeric_limits<short>::max() << endl;
cout << endl;
cout << "min (uint32_t): " << numeric_limits<uint32_t>::min() << endl;
cout << "max (uint32_t): " << numeric_limits<uint32_t>::max() << endl;
cout << "min (int32_t): " << numeric_limits<int32_t>::min() << endl;
cout << "max (int32_t): " << numeric_limits<int32_t>::max() << endl;
cout << "min (int): " << numeric_limits<int>::min() << endl;
cout << "max (int): " << numeric_limits<int>::max() << endl;
cout << endl;
cout << "min (long): " << numeric_limits<long>::min() << endl;
cout << "max (long): " << numeric_limits<long>::max() << endl;
cout << "min (uint64_t): " << numeric_limits<uint64_t>::min() << endl;
cout << "max (uint64_t): " << numeric_limits<uint64_t>::max() << endl;
cout << "min (int64_t): " << numeric_limits<int64_t>::min() << endl;
cout << "max (int64_t): " << numeric_limits<int64_t>::max() << endl;
cout << "min (long long): " << numeric_limits<long long>::min() << endl;
cout << "max (long long): " << numeric_limits<long long>::max() << endl;
cout << endl;
cout << "sizeof (char) " << sizeof (char) << endl;
cout << "sizeof (short) " << sizeof (short) << endl;
cout << "sizeof (int) " << sizeof (int) << endl;
cout << "sizeof (long) " << sizeof (long) << endl;
cout << "sizeof (long long) " << sizeof (long long) << endl;
cout << endl;
cout << "min (float): " << numeric_limits<float>::min() << endl;
cout << "max (float): " << numeric_limits<float>::max() << endl;
cout << "min (double): " << numeric_limits<double>::min() << endl;
cout << "max (double): " << numeric_limits<double>::max() << endl;
cout << "min (long double): " << numeric_limits<long double>::min() << endl;
cout << "max (long double): " << numeric_limits<long double>::max() << endl;
cout << endl;
cout << "sizeof (float) " << sizeof (float) << endl;
cout << "sizeof (double) " << sizeof (double) << endl;
cout << "sizeof (long double) " << sizeof (long double) << endl;
static_assert ( 4 == sizeof (float), "float not 4 bytes.");
static_assert ( 8 == sizeof (double), "double not 8 bytes.");
#ifdef __BORLANDC__
static_assert (10 == sizeof (long double), "Borland/Embarcadero: long double not 10 bytes.");
#endif //#ifdef __BORLANDC__
#ifdef __GNUC__
static_assert (16 == sizeof (long double), "gcc: long double not 16 bytes.");
#endif //#ifdef __GNUC__
cout << endl;
cout << "boolalpha = \'" << boolalpha << "\'" << endl;
cout << "is_signed (char): " << numeric_limits<char>::is_signed << endl;
cout << "is_signed (int8_t): " << numeric_limits<int8_t>::is_signed << endl;
cout << "is_signed (uint8_t): " << numeric_limits<uint8_t>::is_signed << endl;
cout << "is_specialized (string): " << numeric_limits<string>::is_specialized << endl;
} // int main (void)
// based from "The C++ Standard Library" 1st ed. pp. 64-65
#include <iostream>
#include <limits>
using namespace std;
int main (void)
{
#ifdef __BORLANDC__
cout << "__BORLANDC__ defined as " << __BORLANDC__ << endl;
#else
#ifdef __GNUC__
cout << "__GNUC__ defined as " << __GNUC__ << endl;
#else
cout << "Compiler unknown." << endl;
#endif //#ifdef __GNUC__
#endif //#ifdef __BORLANDC__
cout << "min (uint8_t): " << int(numeric_limits<uint8_t>::min()) << endl;
cout << "max (uint8_t): " << int(numeric_limits<uint8_t>::max()) << endl;
cout << "min (int8_t): " << int(numeric_limits<int8_t>::min()) << endl;
cout << "max (int8_t): " << int(numeric_limits<int8_t>::max()) << endl;
cout << "min (char): " << int(numeric_limits<char>::min()) << endl;
cout << "max (char): " << int(numeric_limits<char>::max()) << endl;
cout << endl;
cout << "min (uint16_t): " << numeric_limits<uint16_t>::min() << endl;
cout << "max (uint16_t): " << numeric_limits<uint16_t>::max() << endl;
cout << "min (int16_t): " << numeric_limits<int16_t>::min() << endl;
cout << "max (int16_t): " << numeric_limits<int16_t>::max() << endl;
cout << "min (short): " << numeric_limits<short>::min() << endl;
cout << "max (short): " << numeric_limits<short>::max() << endl;
cout << endl;
cout << "min (uint32_t): " << numeric_limits<uint32_t>::min() << endl;
cout << "max (uint32_t): " << numeric_limits<uint32_t>::max() << endl;
cout << "min (int32_t): " << numeric_limits<int32_t>::min() << endl;
cout << "max (int32_t): " << numeric_limits<int32_t>::max() << endl;
cout << "min (int): " << numeric_limits<int>::min() << endl;
cout << "max (int): " << numeric_limits<int>::max() << endl;
cout << endl;
cout << "min (long): " << numeric_limits<long>::min() << endl;
cout << "max (long): " << numeric_limits<long>::max() << endl;
cout << "min (uint64_t): " << numeric_limits<uint64_t>::min() << endl;
cout << "max (uint64_t): " << numeric_limits<uint64_t>::max() << endl;
cout << "min (int64_t): " << numeric_limits<int64_t>::min() << endl;
cout << "max (int64_t): " << numeric_limits<int64_t>::max() << endl;
cout << "min (long long): " << numeric_limits<long long>::min() << endl;
cout << "max (long long): " << numeric_limits<long long>::max() << endl;
cout << endl;
cout << "sizeof (char) " << sizeof (char) << endl;
cout << "sizeof (short) " << sizeof (short) << endl;
cout << "sizeof (int) " << sizeof (int) << endl;
cout << "sizeof (long) " << sizeof (long) << endl;
cout << "sizeof (long long) " << sizeof (long long) << endl;
cout << endl;
cout << "min (float): " << numeric_limits<float>::min() << endl;
cout << "max (float): " << numeric_limits<float>::max() << endl;
cout << "min (double): " << numeric_limits<double>::min() << endl;
cout << "max (double): " << numeric_limits<double>::max() << endl;
cout << "min (long double): " << numeric_limits<long double>::min() << endl;
cout << "max (long double): " << numeric_limits<long double>::max() << endl;
cout << endl;
cout << "sizeof (float) " << sizeof (float) << endl;
cout << "sizeof (double) " << sizeof (double) << endl;
cout << "sizeof (long double) " << sizeof (long double) << endl;
static_assert ( 4 == sizeof (float), "float not 4 bytes.");
static_assert ( 8 == sizeof (double), "double not 8 bytes.");
#ifdef __BORLANDC__
static_assert (10 == sizeof (long double), "Borland/Embarcadero: long double not 10 bytes.");
#endif //#ifdef __BORLANDC__
#ifdef __GNUC__
static_assert (16 == sizeof (long double), "gcc: long double not 16 bytes.");
#endif //#ifdef __GNUC__
cout << endl;
cout << "boolalpha = \'" << boolalpha << "\'" << endl;
cout << "is_signed (char): " << numeric_limits<char>::is_signed << endl;
cout << "is_signed (int8_t): " << numeric_limits<int8_t>::is_signed << endl;
cout << "is_signed (uint8_t): " << numeric_limits<uint8_t>::is_signed << endl;
cout << "is_specialized (string): " << numeric_limits<string>::is_specialized << endl;
} // int main (void)
-
- Posts: 300
- Joined: Mon Apr 30, 2018 11:51 pm
Re: C++ type system AKA what is exactly int ?
I've worked on TI DSPs where char is 16 bits.Ras wrote: ↑Mon Feb 15, 2021 12:00 am Depends on your target platform. int is at least 16 bits, but may be more. The only case where int doesn't fit in a CPU register is 8 bit controllers such as small AVRs. char is always 8 bits in practice - technically, it is the smallest addressable memory unit that can hold the basic character set. float is not defined precisely, but in practice, it's 32 bits, and double is 64 bits.
C++17 has std::byte, but I haven't checked whether it's guaranteed to be 8 bits.
-
- Posts: 243
- Joined: Sat Mar 11, 2006 8:31 am
- Location: Malmö, Sweden
- Full name: Bo Persson
Re: C++ type system AKA what is exactly int ?
C++ inherited this from C, which was deigned to run on all kinds of different computers. Some of these were 24-bit and 36-bit systems.
Unisys still supports their old 36-bit architecture on new hardware. They don't have a C++ compiler, but they do have a C compiler with 9-bit chars and 36-bit ints.
See https://stackoverflow.com/a/6972551
Rust "solves" this by just not being implemented for the unusual CPUs. Makes the specification a lot easier...
Not really, unless it is important for a variable to be *exactly* 32 bits. Would it hurt if it happened to be 33 bits?So should I write int32_t instead?
In practice, all C++ compilers use 32 bit ints on current PCs. If you ever were to try your program on a machine with a different size, the size of int would likely be the least of your problems. For example, on old MS-DOS you needed special tricks ("far pointers") to access more than 64k of memory. On a potential future system that is highly optimized for 64-bit ints, using int32_t would likely just make your program run slower.
-
- Posts: 243
- Joined: Sat Mar 11, 2006 8:31 am
- Location: Malmö, Sweden
- Full name: Bo Persson
Re: C++ type system AKA what is exactly int ?
No, it is guaranteed to be the size of unsigned char, which is the smallest possible type in C++ (sizeof(byte) == 1).Sesse wrote: ↑Mon Feb 15, 2021 9:30 amI've worked on TI DSPs where char is 16 bits.Ras wrote: ↑Mon Feb 15, 2021 12:00 am Depends on your target platform. int is at least 16 bits, but may be more. The only case where int doesn't fit in a CPU register is 8 bit controllers such as small AVRs. char is always 8 bits in practice - technically, it is the smallest addressable memory unit that can hold the basic character set. float is not defined precisely, but in practice, it's 32 bits, and double is 64 bits.
C++17 has std::byte, but I haven't checked whether it's guaranteed to be 8 bits.
-
- Posts: 4052
- Joined: Thu May 15, 2008 9:57 pm
- Location: Berlin, Germany
- Full name: Sven Schüle
Re: C++ type system AKA what is exactly int ?
Typically I want to run integer calculation with the fastest possible data types (and use int where possible, char or uint64_t where needed) but want to know exactly the size of my data structures (and use types like int32_t, uint16_t etc. for data members). This requires a few type conversions but I try to keep those as local as possible.
Sven Schüle (engine author: Jumbo, KnockOut, Surprise)