C++ type system AKA what is exactly int ?

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

JohnWoe
Posts: 491
Joined: Sat Mar 02, 2013 11:31 pm

C++ type system AKA what is exactly int ?

Post by JohnWoe »

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?
User avatar
mvanthoor
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 ?

Post by mvanthoor »

JohnWoe wrote: Sun Feb 14, 2021 10:10 pm 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?
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").
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.
So, I assume if Rust was available for 16 or 128 bit systems, usize would be 16 or 128 bits on those systems.
Author of Rustic, an engine written in Rust.
Releases | Code | Docs | Progress | CCRL
Sesse
Posts: 300
Joined: Mon Apr 30, 2018 11:51 pm

Re: C++ type system AKA what is exactly int ?

Post by Sesse »

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.
Ras
Posts: 2487
Joined: Tue Aug 30, 2016 8:19 pm
Full name: Rasmus Althoff

Re: C++ type system AKA what is exactly int ?

Post by Ras »

JohnWoe wrote: Sun Feb 14, 2021 10:10 pmEvery time I write int/float/char I wonder what the hell they actually are.
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.
So should I write int32_t instead?
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).
Rasmus Althoff
https://www.ct800.net
benb
Posts: 16
Joined: Sat Dec 12, 2020 5:29 am
Full name: Ben Bradley

Re: C++ type system AKA what is exactly int ?

Post by benb »

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)
benb
Posts: 16
Joined: Sat Dec 12, 2020 5:29 am
Full name: Ben Bradley

Re: C++ type system AKA what is exactly int ?

Post by benb »

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)
Sesse
Posts: 300
Joined: Mon Apr 30, 2018 11:51 pm

Re: C++ type system AKA what is exactly int ?

Post by Sesse »

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.
I've worked on TI DSPs where char is 16 bits.

C++17 has std::byte, but I haven't checked whether it's guaranteed to be 8 bits.
User avatar
Bo Persson
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 ?

Post by Bo Persson »

JohnWoe wrote: Sun Feb 14, 2021 10:10 pm 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.
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. :D

See https://stackoverflow.com/a/6972551

Rust "solves" this by just not being implemented for the unusual CPUs. Makes the specification a lot easier...
So should I write int32_t instead?
Not really, unless it is important for a variable to be *exactly* 32 bits. Would it hurt if it happened to be 33 bits?

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.
User avatar
Bo Persson
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 ?

Post by Bo Persson »

Sesse wrote: Mon Feb 15, 2021 9:30 am
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.
I've worked on TI DSPs where char is 16 bits.

C++17 has std::byte, but I haven't checked whether it's guaranteed to be 8 bits.
No, it is guaranteed to be the size of unsigned char, which is the smallest possible type in C++ (sizeof(byte) == 1).
Sven
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 ?

Post by Sven »

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)