Related
I'm looking for detailed information regarding the size of basic C++ types.
I know that it depends on the architecture (16 bits, 32 bits, 64 bits) and the compiler.
But are there any standards for C++?
I'm using Visual Studio 2008 on a 32-bit architecture. Here is what I get:
char : 1 byte
short : 2 bytes
int : 4 bytes
long : 4 bytes
float : 4 bytes
double: 8 bytes
I tried to find, without much success, reliable information stating the sizes of char, short, int, long, double, float (and other types I didn't think of) under different architectures and compilers.
The C++ standard does not specify the size of integral types in bytes, but it specifies minimum ranges they must be able to hold. You can infer minimum size in bits from the required range. You can infer minimum size in bytes from that and the value of the CHAR_BIT macro that defines the number of bits in a byte. In all but the most obscure platforms it's 8, and it can't be less than 8.
One additional constraint for char is that its size is always 1 byte, or CHAR_BIT bits (hence the name). This is stated explicitly in the standard.
The C standard is a normative reference for the C++ standard, so even though it doesn't state these requirements explicitly, C++ requires the minimum ranges required by the C standard (page 22), which are the same as those from Data Type Ranges on MSDN:
signed char: -127 to 127 (note, not -128 to 127; this accommodates 1's-complement and sign-and-magnitude platforms)
unsigned char: 0 to 255
"plain" char: same range as signed char or unsigned char, implementation-defined
signed short: -32767 to 32767
unsigned short: 0 to 65535
signed int: -32767 to 32767
unsigned int: 0 to 65535
signed long: -2147483647 to 2147483647
unsigned long: 0 to 4294967295
signed long long: -9223372036854775807 to 9223372036854775807
unsigned long long: 0 to 18446744073709551615
A C++ (or C) implementation can define the size of a type in bytes sizeof(type) to any value, as long as
the expression sizeof(type) * CHAR_BIT evaluates to a number of bits high enough to contain required ranges, and
the ordering of type is still valid (e.g. sizeof(int) <= sizeof(long)).
Putting this all together, we are guaranteed that:
char, signed char, and unsigned char are at least 8 bits
signed short, unsigned short, signed int, and unsigned int are at least 16 bits
signed long and unsigned long are at least 32 bits
signed long long and unsigned long long are at least 64 bits
No guarantee is made about the size of float or double except that double provides at least as much precision as float.
The actual implementation-specific ranges can be found in <limits.h> header in C, or <climits> in C++ (or even better, templated std::numeric_limits in <limits> header).
For example, this is how you will find maximum range for int:
C:
#include <limits.h>
const int min_int = INT_MIN;
const int max_int = INT_MAX;
C++:
#include <limits>
const int min_int = std::numeric_limits<int>::min();
const int max_int = std::numeric_limits<int>::max();
For 32-bit systems, the 'de facto' standard is ILP32 — that is, int, long and pointer are all 32-bit quantities.
For 64-bit systems, the primary Unix 'de facto' standard is LP64 — long and pointer are 64-bit (but int is 32-bit). The Windows 64-bit standard is LLP64 — long long and pointer are 64-bit (but long and int are both 32-bit).
At one time, some Unix systems used an ILP64 organization.
None of these de facto standards is legislated by the C standard (ISO/IEC 9899:1999), but all are permitted by it.
And, by definition, sizeof(char) is 1, notwithstanding the test in the Perl configure script.
Note that there were machines (Crays) where CHAR_BIT was much larger than 8. That meant, IIRC, that sizeof(int) was also 1, because both char and int were 32-bit.
In practice there's no such thing. Often you can expect std::size_t to represent the unsigned native integer size on current architecture. i.e. 16-bit, 32-bit or 64-bit but it isn't always the case as pointed out in the comments to this answer.
As far as all the other built-in types go, it really depends on the compiler. Here's two excerpts taken from the current working draft of the latest C++ standard:
There are five standard signed integer types : signed char, short int, int, long int, and long long int. In this list, each type provides at least as much storage as those preceding it in the list.
For each of the standard signed integer types, there exists a corresponding (but different) standard unsigned integer type: unsigned char, unsigned short int, unsigned int, unsigned long int, and unsigned long long int, each of which occupies the same amount of storage and has the same alignment requirements.
If you want to you can statically (compile-time) assert the sizeof these fundamental types. It will alert people to think about porting your code if the sizeof assumptions change.
There is standard.
C90 standard requires that
sizeof(short) <= sizeof(int) <= sizeof(long)
C99 standard requires that
sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long)
Here is the C99 specifications. Page 22 details sizes of different integral types.
Here is the int type sizes (bits) for Windows platforms:
Type C99 Minimum Windows 32bit
char 8 8
short 16 16
int 16 32
long 32 32
long long 64 64
If you are concerned with portability, or you want the name of the type reflects the size, you can look at the header <inttypes.h>, where the following macros are available:
int8_t
int16_t
int32_t
int64_t
int8_t is guaranteed to be 8 bits, and int16_t is guaranteed to be 16 bits, etc.
If you need fixed size types, use types like uint32_t (unsigned integer 32 bits) defined in stdint.h. They are specified in C99.
Updated: C++11 brought the types from TR1 officially into the standard:
long long int
unsigned long long int
And the "sized" types from <cstdint>
int8_t
int16_t
int32_t
int64_t
(and the unsigned counterparts).
Plus you get:
int_least8_t
int_least16_t
int_least32_t
int_least64_t
Plus the unsigned counterparts.
These types represent the smallest integer types with at least the specified number of bits. Likewise there are the "fastest" integer types with at least the specified number of bits:
int_fast8_t
int_fast16_t
int_fast32_t
int_fast64_t
Plus the unsigned versions.
What "fast" means, if anything, is up to the implementation. It need not be the fastest for all purposes either.
The C++ Standard says it like this:
3.9.1, §2:
There are five signed integer types :
"signed char", "short int", "int",
"long int", and "long long int". In
this list, each type provides at least
as much storage as those preceding it
in the list. Plain ints have the
natural size suggested by the
architecture of the execution
environment (44); the other signed
integer types are provided to meet
special needs.
(44) that is, large enough to contain
any value in the range of INT_MIN and
INT_MAX, as defined in the header
<climits>.
The conclusion: It depends on which architecture you're working on. Any other assumption is false.
Nope, there is no standard for type sizes. Standard only requires that:
sizeof(short int) <= sizeof(int) <= sizeof(long int)
The best thing you can do if you want variables of a fixed sizes is to use macros like this:
#ifdef SYSTEM_X
#define WORD int
#else
#define WORD long int
#endif
Then you can use WORD to define your variables. It's not that I like this but it's the most portable way.
For floating point numbers there is a standard (IEEE754): floats are 32 bit and doubles are 64. This is a hardware standard, not a C++ standard, so compilers could theoretically define float and double to some other size, but in practice I've never seen an architecture that used anything different.
We are allowed to define a synonym for the type so we can create our own "standard".
On a machine in which sizeof(int) == 4, we can define:
typedef int int32;
int32 i;
int32 j;
...
So when we transfer the code to a different machine where actually the size of long int is 4, we can just redefine the single occurrence of int.
typedef long int int32;
int32 i;
int32 j;
...
There is a standard and it is specified in the various standards documents (ISO, ANSI and whatnot).
Wikipedia has a great page explaining the various types and the max they may store:
Integer in Computer Science.
However even with a standard C++ compiler you can find out relatively easily using the following code snippet:
#include <iostream>
#include <limits>
int main() {
// Change the template parameter to the various different types.
std::cout << std::numeric_limits<int>::max() << std::endl;
}
Documentation for std::numeric_limits can be found at Roguewave. It includes a plethora of other commands you can call to find out the various limits. This can be used with any arbitrary type that conveys size, for example std::streamsize.
John's answer contains the best description, as those are guaranteed to hold. No matter what platform you are on, there is another good page that goes into more detail as to how many bits each type MUST contain: int types, which are defined in the standard.
I hope this helps!
When it comes to built in types for different architectures and different compilers just run the following code on your architecture with your compiler to see what it outputs. Below shows my Ubuntu 13.04 (Raring Ringtail) 64 bit g++4.7.3 output. Also please note what was answered below which is why the output is ordered as such:
"There are five standard signed integer types: signed char, short int, int, long int, and long long int. In this list, each type provides at least as much storage as those preceding it in the list."
#include <iostream>
int main ( int argc, char * argv[] )
{
std::cout<< "size of char: " << sizeof (char) << std::endl;
std::cout<< "size of short: " << sizeof (short) << std::endl;
std::cout<< "size of int: " << sizeof (int) << std::endl;
std::cout<< "size of long: " << sizeof (long) << std::endl;
std::cout<< "size of long long: " << sizeof (long long) << std::endl;
std::cout<< "size of float: " << sizeof (float) << std::endl;
std::cout<< "size of double: " << sizeof (double) << std::endl;
std::cout<< "size of pointer: " << sizeof (int *) << std::endl;
}
size of char: 1
size of short: 2
size of int: 4
size of long: 8
size of long long: 8
size of float: 4
size of double: 8
size of pointer: 8
1) Table N1 in article "The forgotten problems of 64-bit programs development"
2) "Data model"
You can use:
cout << "size of datatype = " << sizeof(datatype) << endl;
datatype = int, long int etc.
You will be able to see the size for whichever datatype you type.
As mentioned the size should reflect the current architecture. You could take a peak around in limits.h if you want to see how your current compiler is handling things.
If you are interested in a pure C++ solution, I made use of templates and only C++ standard code to define types at compile time based on their bit size.
This make the solution portable across compilers.
The idea behind is very simple: Create a list containing types char, int, short, long, long long (signed and unsigned versions) and the scan the list and by the use of numeric_limits template select the type with given size.
Including this header you got 8 type stdtype::int8, stdtype::int16, stdtype::int32, stdtype::int64, stdtype::uint8, stdtype::uint16, stdtype::uint32, stdtype::uint64.
If some type cannot be represented it will be evaluated to stdtype::null_type also declared in that header.
THE CODE BELOW IS GIVEN WITHOUT WARRANTY, PLEASE DOUBLE CHECK IT.
I'M NEW AT METAPROGRAMMING TOO, FEEL FREE TO EDIT AND CORRECT THIS CODE.
Tested with DevC++ (so a gcc version around 3.5)
#include <limits>
namespace stdtype
{
using namespace std;
/*
* THIS IS THE CLASS USED TO SEMANTICALLY SPECIFY A NULL TYPE.
* YOU CAN USE WHATEVER YOU WANT AND EVEN DRIVE A COMPILE ERROR IF IT IS
* DECLARED/USED.
*
* PLEASE NOTE that C++ std define sizeof of an empty class to be 1.
*/
class null_type{};
/*
* Template for creating lists of types
*
* T is type to hold
* S is the next type_list<T,S> type
*
* Example:
* Creating a list with type int and char:
* typedef type_list<int, type_list<char> > test;
* test::value //int
* test::next::value //char
*/
template <typename T, typename S> struct type_list
{
typedef T value;
typedef S next;
};
/*
* Declaration of template struct for selecting a type from the list
*/
template <typename list, int b, int ctl> struct select_type;
/*
* Find a type with specified "b" bit in list "list"
*
*
*/
template <typename list, int b> struct find_type
{
private:
//Handy name for the type at the head of the list
typedef typename list::value cur_type;
//Number of bits of the type at the head
//CHANGE THIS (compile time) exp TO USE ANOTHER TYPE LEN COMPUTING
enum {cur_type_bits = numeric_limits<cur_type>::digits};
public:
//Select the type at the head if b == cur_type_bits else
//select_type call find_type with list::next
typedef typename select_type<list, b, cur_type_bits>::type type;
};
/*
* This is the specialization for empty list, return the null_type
* OVVERRIDE this struct to ADD CUSTOM BEHAVIOR for the TYPE NOT FOUND case
* (ie search for type with 17 bits on common archs)
*/
template <int b> struct find_type<null_type, b>
{
typedef null_type type;
};
/*
* Primary template for selecting the type at the head of the list if
* it matches the requested bits (b == ctl)
*
* If b == ctl the partial specified templated is evaluated so here we have
* b != ctl. We call find_type on the next element of the list
*/
template <typename list, int b, int ctl> struct select_type
{
typedef typename find_type<typename list::next, b>::type type;
};
/*
* This partial specified templated is used to select top type of a list
* it is called by find_type with the list of value (consumed at each call)
* the bits requested (b) and the current type (top type) length in bits
*
* We specialice the b == ctl case
*/
template <typename list, int b> struct select_type<list, b, b>
{
typedef typename list::value type;
};
/*
* These are the types list, to avoid possible ambiguity (some weird archs)
* we kept signed and unsigned separated
*/
#define UNSIGNED_TYPES type_list<unsigned char, \
type_list<unsigned short, \
type_list<unsigned int, \
type_list<unsigned long, \
type_list<unsigned long long, null_type> > > > >
#define SIGNED_TYPES type_list<signed char, \
type_list<signed short, \
type_list<signed int, \
type_list<signed long, \
type_list<signed long long, null_type> > > > >
/*
* These are acutally typedef used in programs.
*
* Nomenclature is [u]intN where u if present means unsigned, N is the
* number of bits in the integer
*
* find_type is used simply by giving first a type_list then the number of
* bits to search for.
*
* NB. Each type in the type list must had specified the template
* numeric_limits as it is used to compute the type len in (binary) digit.
*/
typedef find_type<UNSIGNED_TYPES, 8>::type uint8;
typedef find_type<UNSIGNED_TYPES, 16>::type uint16;
typedef find_type<UNSIGNED_TYPES, 32>::type uint32;
typedef find_type<UNSIGNED_TYPES, 64>::type uint64;
typedef find_type<SIGNED_TYPES, 7>::type int8;
typedef find_type<SIGNED_TYPES, 15>::type int16;
typedef find_type<SIGNED_TYPES, 31>::type int32;
typedef find_type<SIGNED_TYPES, 63>::type int64;
}
As others have answered, the "standards" all leave most of the details as "implementation defined" and only state that type "char" is at leat "char_bis" wide, and that "char <= short <= int <= long <= long long" (float and double are pretty much consistent with the IEEE floating point standards, and long double is typically same as double--but may be larger on more current implementations).
Part of the reasons for not having very specific and exact values is because languages like C/C++ were designed to be portable to a large number of hardware platforms--Including computer systems in which the "char" word-size may be 4-bits or 7-bits, or even some value other than the "8-/16-/32-/64-bit" computers the average home computer user is exposed to. (Word-size here meaning how many bits wide the system normally operates on--Again, it's not always 8-bits as home computer users may expect.)
If you really need a object (in the sense of a series of bits representing an integral value) of a specific number of bits, most compilers have some method of specifying that; But it's generally not portable, even between compilers made by the ame company but for different platforms. Some standards and practices (especially limits.h and the like) are common enough that most compilers will have support for determining at the best-fit type for a specific range of values, but not the number of bits used. (That is, if you know you need to hold values between 0 and 127, you can determine that your compiler supports an "int8" type of 8-bits which will be large enought to hold the full range desired, but not something like an "int7" type which would be an exact match for 7-bits.)
Note: Many Un*x source packages used "./configure" script which will probe the compiler/system's capabilities and output a suitable Makefile and config.h. You might examine some of these scripts to see how they work and how they probe the comiler/system capabilities, and follow their lead.
I notice that all the other answers here have focused almost exclusively on integral types, while the questioner also asked about floating-points.
I don't think the C++ standard requires it, but compilers for the most common platforms these days generally follow the IEEE754 standard for their floating-point numbers. This standard specifies four types of binary floating-point (as well as some BCD formats, which I've never seen support for in C++ compilers):
Half precision (binary16) - 11-bit significand, exponent range -14 to 15
Single precision (binary32) - 24-bit significand, exponent range -126 to 127
Double precision (binary64) - 53-bit significand, exponent range -1022 to 1023
Quadruple precision (binary128) - 113-bit significand, exponent range -16382 to 16383
How does this map onto C++ types, then? Generally the float uses single precision; thus, sizeof(float) = 4. Then double uses double precision (I believe that's the source of the name double), and long double may be either double or quadruple precision (it's quadruple on my system, but on 32-bit systems it may be double). I don't know of any compilers that offer half precision floating-points.
In summary, this is the usual:
sizeof(float) = 4
sizeof(double) = 8
sizeof(long double) = 8 or 16
unsigned char bits = sizeof(X) << 3;
where X is a char,int,long etc.. will give you size of X in bits.
From Alex B The C++ standard does not specify the size of integral types in bytes, but it specifies minimum ranges they must be able to hold. You can infer minimum size in bits from the required range. You can infer minimum size in bytes from that and the value of the CHAR_BIT macro that defines the number of bits in a byte (in all but the most obscure platforms it's 8, and it can't be less than 8).
One additional constraint for char is that its size is always 1 byte, or CHAR_BIT bits (hence the name).
Minimum ranges required by the standard (page 22) are:
and Data Type Ranges on MSDN:
signed char: -127 to 127 (note, not -128 to 127; this accommodates 1's-complement platforms)
unsigned char: 0 to 255
"plain" char: -127 to 127 or 0 to 255 (depends on default char signedness)
signed short: -32767 to 32767
unsigned short: 0 to 65535
signed int: -32767 to 32767
unsigned int: 0 to 65535
signed long: -2147483647 to 2147483647
unsigned long: 0 to 4294967295
signed long long: -9223372036854775807 to 9223372036854775807
unsigned long long: 0 to 18446744073709551615
A C++ (or C) implementation can define the size of a type in bytes sizeof(type) to any value, as long as
the expression sizeof(type) * CHAR_BIT evaluates to the number of bits enough to contain required ranges, and
the ordering of type is still valid (e.g. sizeof(int) <= sizeof(long)).
The actual implementation-specific ranges can be found in header in C, or in C++ (or even better, templated std::numeric_limits in header).
For example, this is how you will find maximum range for int:
C:
#include <limits.h>
const int min_int = INT_MIN;
const int max_int = INT_MAX;
C++:
#include <limits>
const int min_int = std::numeric_limits<int>::min();
const int max_int = std::numeric_limits<int>::max();
This is correct, however, you were also right in saying that:
char : 1 byte
short : 2 bytes
int : 4 bytes
long : 4 bytes
float : 4 bytes
double : 8 bytes
Because 32 bit architectures are still the default and most used, and they have kept these standard sizes since the pre-32 bit days when memory was less available, and for backwards compatibility and standardization it remained the same. Even 64 bit systems tend to use these and have extentions/modifications.
Please reference this for more information:
http://en.cppreference.com/w/cpp/language/types
As you mentioned - it largely depends upon the compiler and the platform. For this, check the ANSI standard, http://home.att.net/~jackklein/c/inttypes.html
Here is the one for the Microsoft compiler: Data Type Ranges.
You can use variables provided by libraries such as OpenGL, Qt, etc.
For example, Qt provides qint8 (guaranteed to be 8-bit on all platforms supported by Qt), qint16, qint32, qint64, quint8, quint16, quint32, quint64, etc.
On a 64-bit machine:
int: 4
long: 8
long long: 8
void*: 8
size_t: 8
There are four types of integers based on size:
short integer: 2 byte
long integer: 4 byte
long long integer: 8 byte
integer: depends upon the compiler (16 bit, 32 bit, or 64 bit)
I am transitioning from Java to C++ and have some questions about the long data type. In Java, to hold an integer greater than 232, you would simply write long x;. However, in C++, it seems that long is both a data type and a modifier.
There seems to be several ways to use long:
long x;
long long x;
long int x;
long long int x;
Also, it seems there are things such as:
long double x;
and so on.
What is the difference between all of these various data types, and do they all have the same purpose?
long and long int are identical. So are long long and long long int. In both cases, the int is optional.
As to the difference between the two sets, the C++ standard mandates minimum ranges for each, and that long long is at least as wide as long.
The controlling parts of the standard (C++11, but this has been around for a long time) are, for one, 3.9.1 Fundamental types, section 2 (a later section gives similar rules for the unsigned integral types):
There are five standard signed integer types : signed char, short int, int, long int, and long long int. In this list, each type provides at least as much storage as those preceding it in the list.
There's also a table 9 in 7.1.6.2 Simple type specifiers, which shows the "mappings" of the specifiers to actual types (showing that the int is optional), a section of which is shown below:
Specifier(s) Type
------------- -------------
long long int long long int
long long long long int
long int long int
long long int
Note the distinction there between the specifier and the type. The specifier is how you tell the compiler what the type is but you can use different specifiers to end up at the same type.
Hence long on its own is neither a type nor a modifier as your question posits, it's simply a specifier for the long int type. Ditto for long long being a specifier for the long long int type.
Although the C++ standard itself doesn't specify the minimum ranges of integral types, it does cite C99, in 1.2 Normative references, as applying. Hence the minimal ranges as set out in C99 5.2.4.2.1 Sizes of integer types <limits.h> are applicable.
In terms of long double, that's actually a floating point value rather than an integer. Similarly to the integral types, it's required to have at least as much precision as a double and to provide a superset of values over that type (meaning at least those values, not necessarily more values).
Long and long int are at least 32 bits.
long long and long long int are at least 64 bits. You must be using a c99 compiler or better.
long doubles are a bit odd. Look them up on Wikipedia for details.
long is equivalent to long int, just as short is equivalent to short int. A long int is a signed integral type that is at least 32 bits, while a long long or long long int is a signed integral type is at least 64 bits.
This doesn't necessarily mean that a long long is wider than a long. Many platforms / ABIs use the LP64 model - where long (and pointers) are 64 bits wide. Win64 uses the LLP64, where long is still 32 bits, and long long (and pointers) are 64 bits wide.
There's a good summary of 64-bit data models here.
long double doesn't guarantee much other than it will be at least as wide as a double.
While in Java a long is always 64 bits, in C++ this depends on computer architecture and operating system. For example, a long is 64 bits on Linux and 32 bits on Windows (this was done to keep backwards-compatability, allowing 32-bit programs to compile on 64-bit Windows without any changes). long int is a synonym for long.
Later on, long long was introduced to mean "long (64 bits) on Windows for real this time". long long int is a synonym for this.
It is considered good C++ style to avoid short, int, long etc. and instead use:
std::int8_t # exactly 8 bits
std::int16_t # exactly 16 bits
std::int32_t # exactly 32 bits
std::int64_t # exactly 64 bits
std::size_t # can hold all possible object sizes, used for indexing
You can use these int*_t types by including the <cstdint> header. size_t is in <stdlib.h>.
This looks confusing because you are taking long as a datatype itself.
long is nothing but just the shorthand for long int when you are using it alone.
long is a modifier, you can use it with double also as long double.
long == long int.
Both of them take 4 bytes.
Historically, in early C times, when processors had 8 or 16 bit wordlength,intwas identical to todays short(16 bit). In a certain sense, int is a more abstract data type thanchar,short,longorlong long, as you cannot be sure about the bitwidth.
When definingint n;you could translate this with "give me the best compromise of bitwidth and speed on this machine for n". Maybe in the future you should expect compilers to translateintto be 64 bit. So when you want your variable to have 32 bits and not more, better use an explicitlongas data type.
[Edit: #include <stdint.h> seems to be the proper way to ensure bitwidths using the int##_t types, though it's not yet part of the standard.]
There is no deffirence, (long long x ) is equivalent to (long long int x ), but the second confirms that variable x is integer
I've been programming in C++ for quite a while now and I am pretty familiar with most of the stuff. One thing that I've never understood though is the 'long' data type.
I googled it but I still don't know what it is for. I've found pages that say it is the same size and has the same range as an int. So what would be the point in using it?
I found another stack overflow question regarding this here:
Difference between long and int data types
And it seems that the only difference between the two is that sometimes the size is different on different systems. Does that mean that an application that uses long on a 64bit machine won't work on a 32bit machine? If so then wouldn't it be better to not use them at all?
Also I noticed stuff called "long int" or even "long long"! Is it a data type or a modifier?
It is compiler dependent. My standards-fu is a bit rusty but I believe it is defined as follows:
char <= short <= int <= long <= long long
where:
char >= 8 bits
short >= 16 bits
int >= 16 bits
long >= 32 bits
long long >= 64 bits
Which means that it is perfectly valid to have char = short = int = long = long long = 64bits and in fact compilers of some DSPs are designed that way.
This underscores the importance of actually reading your compiler documentation.
I noticed stuff called "long int" or even "long long"! Is it a data type or a modifier?
long int is the same as long (just as short int is the same as short).
long long is a distinct data type introduced by several compilers and adopted by C++0x.
Note that there is no such thing as long long long:
error: 'long long long' is too long for GCC
From one of the answers in the question you linked:
The long must be at least the same size as an int, and possibly, but not necessarily, longer.
I can't think of a better way to explain it.
long is guaranteed (at least) 32 bits. int is only guaranteed (at least) 16 bits. on 16- and 8-bit systems long provided range at a cost of efficiency.
cheers & hth.,
This is what the C++03 standard says (3.9.1/2) :
There are four signed integer types:
“signed char”, “short int”, “int”, and
“long int.” In this list, each type
provides at least as much storage as
those preceding it in the list.
So : sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long)
This is what the C++0x (3.9.1/2) and C99 (6.2.5/4) standards say :
There are five standard signed integer
types, designated as signed char,
short int, int, long int, and long
long int.
long is synonym of long int
long long doesn't exist in C++03, but will in C++0x.
I googled it but I still don't know
what its for. I've found pages that
say its the same size and has the same
range as an int. So what would be the
point in using it?
I've wondered the same thing. And concluded that long is now useless.
Prior to the rise of 64-bit systems, the de facto standard for C integer types was:
char = (u)int8_t (Note that C predates Unicode.)
short = int16_t
int = intptr_t [until 64-bit], int_fast16_t
long = int32_t [until 64-bit], intmax_t [until 1999]
long long = int64_t or intmax_t
Today, however, long has no consistent semantics.
If you want an integer that is guaranteed to be 32 bit or 64 bit, there are such types, e.g. int64_t. If you really want to ensure your int are of such a size, use these types instead of long, long long, etc. You'll need to include cstdint for these (stdint.h in C).
What is the relation between word length, character size, integer size, and byte in C++?
The standard requires that certain types have minimum sizes (short is at least 16 bits, int is at least 16 bits, etc), and that some groups of type are ordered (sizeof(int) >= sizeof(short) >= sizeof(char)).
In C++ a char must be large enough to hold any character in the implemetation's basic character set.
int has the "natural size suggested by the architecture of the execution environment". Note that this means that an int does not need to be at least 32-bits in size. Implementations where int is 16 bits are common (think embedded ot MS-DOS).
The following are taken from various parts of the C++98 and C99 standards:
long int has to be at least as large as int
int has to be at least as large as short
short has to be at least as large as char
Note that they could all be the same size.
Also (assuming a two's complement implementation):
long int has to be at least 32-bits
int has to be at least 16-bits
short has to be at least 16-bits
char has to be at least 8 bits
The Standard doesn't know this "word" thingy used by processors. But it says the type "int" should have the natural size for a execution environment. But even for 64 bit environments, int is usually only 32 bits. So "word" in Standard terms has pretty much no common meaning (except for the common English "word" of course).
Character size is the size of a character. Depends on what character you talk about. Character types are char, unsigned char and signed char. Also wchar_t is used to store characters that can have any size (determined by the implementation - but must use one of the integer types as its underlying type. Much like enumerations), while char/signed char or unsigned char has to have one byte. That means that one byte has as much bits as one char has. If an implementation says one object of type char has 16 bits, then a byte has 16 bits too.
Now a byte is the size that one char occupies. It's a unit, not some specific type. There is not much more about it, just that it is the unit that you can access memory. I.e you do not have pointer access to bit-fields, but you have access to units starting at one byte.
"Integer size" now is pretty wide. What do you mean? All of bool, char, short, int, long and their unsinged counterparts are integers. Their range is what i would call "integer size" and it is documented in the C standard - taken over by the C++ Standard. For signed char the range is from -127 <-> 127, for short and int it is the same and is -2^15+1 <-> 2^15-1 and for long it is -2^31+1 <-> 2^31-1. Their unsigned counterparts range from 0 up to 2^8-1, 2^16-1 and 2^32-1 respectively. Those are however minimal sizes. That is, an int may not have maximal size 2^14 on any platform, because that is less than 2^15-1 of course. It follows for those values that a minimum of bits is required. For char that is 8, for short/int that is 16 and for long that is 32. Two's-complement representation for negative numbers is not required, which is why the negative value is not -128 instead of -127 for example for signed char.
Standard C++ doesn't have a datatype called word or byte. The rest are well defined as ranges. The base is a char which has of CHAR_BITS bits. The most commonly used value of CHAR_BITS is 8.
sizeof( char ) == 1 ( one byte ) (in c++, in C - not specified)
sizeof( int ) >= sizeof( char )
word - not c++ type, usualy in computer architecture it mean 2 bytes
Kind of depends on what you mean by relation. The size of numeric types is generally a multiple of the machine word size. A byte is a byte is a byte -- 8 bits, no more, no less. A character is defined in the standard as a single unsigned byte I believe (check your ARM for details).
The general rule is, don't make any assumptions about the actual size of data types. The standard specifies relationships between the types such as a "long" integer will be either the same size or larger than an "int". Individual implementations of the language will pick specific sizes for the types that are convenient for them. For example, a compiler for a 64-bit processor will choose different sizes than a compiler for a 32-bit processor.
You can use the sizeof() operator to examine the specific sizes for the compiler you are using (on the specific target architecture).
I'm looking for detailed information regarding the size of basic C++ types.
I know that it depends on the architecture (16 bits, 32 bits, 64 bits) and the compiler.
But are there any standards for C++?
I'm using Visual Studio 2008 on a 32-bit architecture. Here is what I get:
char : 1 byte
short : 2 bytes
int : 4 bytes
long : 4 bytes
float : 4 bytes
double: 8 bytes
I tried to find, without much success, reliable information stating the sizes of char, short, int, long, double, float (and other types I didn't think of) under different architectures and compilers.
The C++ standard does not specify the size of integral types in bytes, but it specifies minimum ranges they must be able to hold. You can infer minimum size in bits from the required range. You can infer minimum size in bytes from that and the value of the CHAR_BIT macro that defines the number of bits in a byte. In all but the most obscure platforms it's 8, and it can't be less than 8.
One additional constraint for char is that its size is always 1 byte, or CHAR_BIT bits (hence the name). This is stated explicitly in the standard.
The C standard is a normative reference for the C++ standard, so even though it doesn't state these requirements explicitly, C++ requires the minimum ranges required by the C standard (page 22), which are the same as those from Data Type Ranges on MSDN:
signed char: -127 to 127 (note, not -128 to 127; this accommodates 1's-complement and sign-and-magnitude platforms)
unsigned char: 0 to 255
"plain" char: same range as signed char or unsigned char, implementation-defined
signed short: -32767 to 32767
unsigned short: 0 to 65535
signed int: -32767 to 32767
unsigned int: 0 to 65535
signed long: -2147483647 to 2147483647
unsigned long: 0 to 4294967295
signed long long: -9223372036854775807 to 9223372036854775807
unsigned long long: 0 to 18446744073709551615
A C++ (or C) implementation can define the size of a type in bytes sizeof(type) to any value, as long as
the expression sizeof(type) * CHAR_BIT evaluates to a number of bits high enough to contain required ranges, and
the ordering of type is still valid (e.g. sizeof(int) <= sizeof(long)).
Putting this all together, we are guaranteed that:
char, signed char, and unsigned char are at least 8 bits
signed short, unsigned short, signed int, and unsigned int are at least 16 bits
signed long and unsigned long are at least 32 bits
signed long long and unsigned long long are at least 64 bits
No guarantee is made about the size of float or double except that double provides at least as much precision as float.
The actual implementation-specific ranges can be found in <limits.h> header in C, or <climits> in C++ (or even better, templated std::numeric_limits in <limits> header).
For example, this is how you will find maximum range for int:
C:
#include <limits.h>
const int min_int = INT_MIN;
const int max_int = INT_MAX;
C++:
#include <limits>
const int min_int = std::numeric_limits<int>::min();
const int max_int = std::numeric_limits<int>::max();
For 32-bit systems, the 'de facto' standard is ILP32 — that is, int, long and pointer are all 32-bit quantities.
For 64-bit systems, the primary Unix 'de facto' standard is LP64 — long and pointer are 64-bit (but int is 32-bit). The Windows 64-bit standard is LLP64 — long long and pointer are 64-bit (but long and int are both 32-bit).
At one time, some Unix systems used an ILP64 organization.
None of these de facto standards is legislated by the C standard (ISO/IEC 9899:1999), but all are permitted by it.
And, by definition, sizeof(char) is 1, notwithstanding the test in the Perl configure script.
Note that there were machines (Crays) where CHAR_BIT was much larger than 8. That meant, IIRC, that sizeof(int) was also 1, because both char and int were 32-bit.
In practice there's no such thing. Often you can expect std::size_t to represent the unsigned native integer size on current architecture. i.e. 16-bit, 32-bit or 64-bit but it isn't always the case as pointed out in the comments to this answer.
As far as all the other built-in types go, it really depends on the compiler. Here's two excerpts taken from the current working draft of the latest C++ standard:
There are five standard signed integer types : signed char, short int, int, long int, and long long int. In this list, each type provides at least as much storage as those preceding it in the list.
For each of the standard signed integer types, there exists a corresponding (but different) standard unsigned integer type: unsigned char, unsigned short int, unsigned int, unsigned long int, and unsigned long long int, each of which occupies the same amount of storage and has the same alignment requirements.
If you want to you can statically (compile-time) assert the sizeof these fundamental types. It will alert people to think about porting your code if the sizeof assumptions change.
There is standard.
C90 standard requires that
sizeof(short) <= sizeof(int) <= sizeof(long)
C99 standard requires that
sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long)
Here is the C99 specifications. Page 22 details sizes of different integral types.
Here is the int type sizes (bits) for Windows platforms:
Type C99 Minimum Windows 32bit
char 8 8
short 16 16
int 16 32
long 32 32
long long 64 64
If you are concerned with portability, or you want the name of the type reflects the size, you can look at the header <inttypes.h>, where the following macros are available:
int8_t
int16_t
int32_t
int64_t
int8_t is guaranteed to be 8 bits, and int16_t is guaranteed to be 16 bits, etc.
If you need fixed size types, use types like uint32_t (unsigned integer 32 bits) defined in stdint.h. They are specified in C99.
Updated: C++11 brought the types from TR1 officially into the standard:
long long int
unsigned long long int
And the "sized" types from <cstdint>
int8_t
int16_t
int32_t
int64_t
(and the unsigned counterparts).
Plus you get:
int_least8_t
int_least16_t
int_least32_t
int_least64_t
Plus the unsigned counterparts.
These types represent the smallest integer types with at least the specified number of bits. Likewise there are the "fastest" integer types with at least the specified number of bits:
int_fast8_t
int_fast16_t
int_fast32_t
int_fast64_t
Plus the unsigned versions.
What "fast" means, if anything, is up to the implementation. It need not be the fastest for all purposes either.
The C++ Standard says it like this:
3.9.1, §2:
There are five signed integer types :
"signed char", "short int", "int",
"long int", and "long long int". In
this list, each type provides at least
as much storage as those preceding it
in the list. Plain ints have the
natural size suggested by the
architecture of the execution
environment (44); the other signed
integer types are provided to meet
special needs.
(44) that is, large enough to contain
any value in the range of INT_MIN and
INT_MAX, as defined in the header
<climits>.
The conclusion: It depends on which architecture you're working on. Any other assumption is false.
Nope, there is no standard for type sizes. Standard only requires that:
sizeof(short int) <= sizeof(int) <= sizeof(long int)
The best thing you can do if you want variables of a fixed sizes is to use macros like this:
#ifdef SYSTEM_X
#define WORD int
#else
#define WORD long int
#endif
Then you can use WORD to define your variables. It's not that I like this but it's the most portable way.
For floating point numbers there is a standard (IEEE754): floats are 32 bit and doubles are 64. This is a hardware standard, not a C++ standard, so compilers could theoretically define float and double to some other size, but in practice I've never seen an architecture that used anything different.
We are allowed to define a synonym for the type so we can create our own "standard".
On a machine in which sizeof(int) == 4, we can define:
typedef int int32;
int32 i;
int32 j;
...
So when we transfer the code to a different machine where actually the size of long int is 4, we can just redefine the single occurrence of int.
typedef long int int32;
int32 i;
int32 j;
...
There is a standard and it is specified in the various standards documents (ISO, ANSI and whatnot).
Wikipedia has a great page explaining the various types and the max they may store:
Integer in Computer Science.
However even with a standard C++ compiler you can find out relatively easily using the following code snippet:
#include <iostream>
#include <limits>
int main() {
// Change the template parameter to the various different types.
std::cout << std::numeric_limits<int>::max() << std::endl;
}
Documentation for std::numeric_limits can be found at Roguewave. It includes a plethora of other commands you can call to find out the various limits. This can be used with any arbitrary type that conveys size, for example std::streamsize.
John's answer contains the best description, as those are guaranteed to hold. No matter what platform you are on, there is another good page that goes into more detail as to how many bits each type MUST contain: int types, which are defined in the standard.
I hope this helps!
When it comes to built in types for different architectures and different compilers just run the following code on your architecture with your compiler to see what it outputs. Below shows my Ubuntu 13.04 (Raring Ringtail) 64 bit g++4.7.3 output. Also please note what was answered below which is why the output is ordered as such:
"There are five standard signed integer types: signed char, short int, int, long int, and long long int. In this list, each type provides at least as much storage as those preceding it in the list."
#include <iostream>
int main ( int argc, char * argv[] )
{
std::cout<< "size of char: " << sizeof (char) << std::endl;
std::cout<< "size of short: " << sizeof (short) << std::endl;
std::cout<< "size of int: " << sizeof (int) << std::endl;
std::cout<< "size of long: " << sizeof (long) << std::endl;
std::cout<< "size of long long: " << sizeof (long long) << std::endl;
std::cout<< "size of float: " << sizeof (float) << std::endl;
std::cout<< "size of double: " << sizeof (double) << std::endl;
std::cout<< "size of pointer: " << sizeof (int *) << std::endl;
}
size of char: 1
size of short: 2
size of int: 4
size of long: 8
size of long long: 8
size of float: 4
size of double: 8
size of pointer: 8
1) Table N1 in article "The forgotten problems of 64-bit programs development"
2) "Data model"
You can use:
cout << "size of datatype = " << sizeof(datatype) << endl;
datatype = int, long int etc.
You will be able to see the size for whichever datatype you type.
As mentioned the size should reflect the current architecture. You could take a peak around in limits.h if you want to see how your current compiler is handling things.
If you are interested in a pure C++ solution, I made use of templates and only C++ standard code to define types at compile time based on their bit size.
This make the solution portable across compilers.
The idea behind is very simple: Create a list containing types char, int, short, long, long long (signed and unsigned versions) and the scan the list and by the use of numeric_limits template select the type with given size.
Including this header you got 8 type stdtype::int8, stdtype::int16, stdtype::int32, stdtype::int64, stdtype::uint8, stdtype::uint16, stdtype::uint32, stdtype::uint64.
If some type cannot be represented it will be evaluated to stdtype::null_type also declared in that header.
THE CODE BELOW IS GIVEN WITHOUT WARRANTY, PLEASE DOUBLE CHECK IT.
I'M NEW AT METAPROGRAMMING TOO, FEEL FREE TO EDIT AND CORRECT THIS CODE.
Tested with DevC++ (so a gcc version around 3.5)
#include <limits>
namespace stdtype
{
using namespace std;
/*
* THIS IS THE CLASS USED TO SEMANTICALLY SPECIFY A NULL TYPE.
* YOU CAN USE WHATEVER YOU WANT AND EVEN DRIVE A COMPILE ERROR IF IT IS
* DECLARED/USED.
*
* PLEASE NOTE that C++ std define sizeof of an empty class to be 1.
*/
class null_type{};
/*
* Template for creating lists of types
*
* T is type to hold
* S is the next type_list<T,S> type
*
* Example:
* Creating a list with type int and char:
* typedef type_list<int, type_list<char> > test;
* test::value //int
* test::next::value //char
*/
template <typename T, typename S> struct type_list
{
typedef T value;
typedef S next;
};
/*
* Declaration of template struct for selecting a type from the list
*/
template <typename list, int b, int ctl> struct select_type;
/*
* Find a type with specified "b" bit in list "list"
*
*
*/
template <typename list, int b> struct find_type
{
private:
//Handy name for the type at the head of the list
typedef typename list::value cur_type;
//Number of bits of the type at the head
//CHANGE THIS (compile time) exp TO USE ANOTHER TYPE LEN COMPUTING
enum {cur_type_bits = numeric_limits<cur_type>::digits};
public:
//Select the type at the head if b == cur_type_bits else
//select_type call find_type with list::next
typedef typename select_type<list, b, cur_type_bits>::type type;
};
/*
* This is the specialization for empty list, return the null_type
* OVVERRIDE this struct to ADD CUSTOM BEHAVIOR for the TYPE NOT FOUND case
* (ie search for type with 17 bits on common archs)
*/
template <int b> struct find_type<null_type, b>
{
typedef null_type type;
};
/*
* Primary template for selecting the type at the head of the list if
* it matches the requested bits (b == ctl)
*
* If b == ctl the partial specified templated is evaluated so here we have
* b != ctl. We call find_type on the next element of the list
*/
template <typename list, int b, int ctl> struct select_type
{
typedef typename find_type<typename list::next, b>::type type;
};
/*
* This partial specified templated is used to select top type of a list
* it is called by find_type with the list of value (consumed at each call)
* the bits requested (b) and the current type (top type) length in bits
*
* We specialice the b == ctl case
*/
template <typename list, int b> struct select_type<list, b, b>
{
typedef typename list::value type;
};
/*
* These are the types list, to avoid possible ambiguity (some weird archs)
* we kept signed and unsigned separated
*/
#define UNSIGNED_TYPES type_list<unsigned char, \
type_list<unsigned short, \
type_list<unsigned int, \
type_list<unsigned long, \
type_list<unsigned long long, null_type> > > > >
#define SIGNED_TYPES type_list<signed char, \
type_list<signed short, \
type_list<signed int, \
type_list<signed long, \
type_list<signed long long, null_type> > > > >
/*
* These are acutally typedef used in programs.
*
* Nomenclature is [u]intN where u if present means unsigned, N is the
* number of bits in the integer
*
* find_type is used simply by giving first a type_list then the number of
* bits to search for.
*
* NB. Each type in the type list must had specified the template
* numeric_limits as it is used to compute the type len in (binary) digit.
*/
typedef find_type<UNSIGNED_TYPES, 8>::type uint8;
typedef find_type<UNSIGNED_TYPES, 16>::type uint16;
typedef find_type<UNSIGNED_TYPES, 32>::type uint32;
typedef find_type<UNSIGNED_TYPES, 64>::type uint64;
typedef find_type<SIGNED_TYPES, 7>::type int8;
typedef find_type<SIGNED_TYPES, 15>::type int16;
typedef find_type<SIGNED_TYPES, 31>::type int32;
typedef find_type<SIGNED_TYPES, 63>::type int64;
}
As others have answered, the "standards" all leave most of the details as "implementation defined" and only state that type "char" is at leat "char_bis" wide, and that "char <= short <= int <= long <= long long" (float and double are pretty much consistent with the IEEE floating point standards, and long double is typically same as double--but may be larger on more current implementations).
Part of the reasons for not having very specific and exact values is because languages like C/C++ were designed to be portable to a large number of hardware platforms--Including computer systems in which the "char" word-size may be 4-bits or 7-bits, or even some value other than the "8-/16-/32-/64-bit" computers the average home computer user is exposed to. (Word-size here meaning how many bits wide the system normally operates on--Again, it's not always 8-bits as home computer users may expect.)
If you really need a object (in the sense of a series of bits representing an integral value) of a specific number of bits, most compilers have some method of specifying that; But it's generally not portable, even between compilers made by the ame company but for different platforms. Some standards and practices (especially limits.h and the like) are common enough that most compilers will have support for determining at the best-fit type for a specific range of values, but not the number of bits used. (That is, if you know you need to hold values between 0 and 127, you can determine that your compiler supports an "int8" type of 8-bits which will be large enought to hold the full range desired, but not something like an "int7" type which would be an exact match for 7-bits.)
Note: Many Un*x source packages used "./configure" script which will probe the compiler/system's capabilities and output a suitable Makefile and config.h. You might examine some of these scripts to see how they work and how they probe the comiler/system capabilities, and follow their lead.
I notice that all the other answers here have focused almost exclusively on integral types, while the questioner also asked about floating-points.
I don't think the C++ standard requires it, but compilers for the most common platforms these days generally follow the IEEE754 standard for their floating-point numbers. This standard specifies four types of binary floating-point (as well as some BCD formats, which I've never seen support for in C++ compilers):
Half precision (binary16) - 11-bit significand, exponent range -14 to 15
Single precision (binary32) - 24-bit significand, exponent range -126 to 127
Double precision (binary64) - 53-bit significand, exponent range -1022 to 1023
Quadruple precision (binary128) - 113-bit significand, exponent range -16382 to 16383
How does this map onto C++ types, then? Generally the float uses single precision; thus, sizeof(float) = 4. Then double uses double precision (I believe that's the source of the name double), and long double may be either double or quadruple precision (it's quadruple on my system, but on 32-bit systems it may be double). I don't know of any compilers that offer half precision floating-points.
In summary, this is the usual:
sizeof(float) = 4
sizeof(double) = 8
sizeof(long double) = 8 or 16
unsigned char bits = sizeof(X) << 3;
where X is a char,int,long etc.. will give you size of X in bits.
From Alex B The C++ standard does not specify the size of integral types in bytes, but it specifies minimum ranges they must be able to hold. You can infer minimum size in bits from the required range. You can infer minimum size in bytes from that and the value of the CHAR_BIT macro that defines the number of bits in a byte (in all but the most obscure platforms it's 8, and it can't be less than 8).
One additional constraint for char is that its size is always 1 byte, or CHAR_BIT bits (hence the name).
Minimum ranges required by the standard (page 22) are:
and Data Type Ranges on MSDN:
signed char: -127 to 127 (note, not -128 to 127; this accommodates 1's-complement platforms)
unsigned char: 0 to 255
"plain" char: -127 to 127 or 0 to 255 (depends on default char signedness)
signed short: -32767 to 32767
unsigned short: 0 to 65535
signed int: -32767 to 32767
unsigned int: 0 to 65535
signed long: -2147483647 to 2147483647
unsigned long: 0 to 4294967295
signed long long: -9223372036854775807 to 9223372036854775807
unsigned long long: 0 to 18446744073709551615
A C++ (or C) implementation can define the size of a type in bytes sizeof(type) to any value, as long as
the expression sizeof(type) * CHAR_BIT evaluates to the number of bits enough to contain required ranges, and
the ordering of type is still valid (e.g. sizeof(int) <= sizeof(long)).
The actual implementation-specific ranges can be found in header in C, or in C++ (or even better, templated std::numeric_limits in header).
For example, this is how you will find maximum range for int:
C:
#include <limits.h>
const int min_int = INT_MIN;
const int max_int = INT_MAX;
C++:
#include <limits>
const int min_int = std::numeric_limits<int>::min();
const int max_int = std::numeric_limits<int>::max();
This is correct, however, you were also right in saying that:
char : 1 byte
short : 2 bytes
int : 4 bytes
long : 4 bytes
float : 4 bytes
double : 8 bytes
Because 32 bit architectures are still the default and most used, and they have kept these standard sizes since the pre-32 bit days when memory was less available, and for backwards compatibility and standardization it remained the same. Even 64 bit systems tend to use these and have extentions/modifications.
Please reference this for more information:
http://en.cppreference.com/w/cpp/language/types
As you mentioned - it largely depends upon the compiler and the platform. For this, check the ANSI standard, http://home.att.net/~jackklein/c/inttypes.html
Here is the one for the Microsoft compiler: Data Type Ranges.
You can use variables provided by libraries such as OpenGL, Qt, etc.
For example, Qt provides qint8 (guaranteed to be 8-bit on all platforms supported by Qt), qint16, qint32, qint64, quint8, quint16, quint32, quint64, etc.
On a 64-bit machine:
int: 4
long: 8
long long: 8
void*: 8
size_t: 8
There are four types of integers based on size:
short integer: 2 byte
long integer: 4 byte
long long integer: 8 byte
integer: depends upon the compiler (16 bit, 32 bit, or 64 bit)