I know I can rely on sizeof(char) == 1, but what about sizeof(uint32_t) and sizeof(uint8_t)?
Shouldn't it be 32bit (8bit) in size guessing from the name?
Thanks!
The fixed-sized types will always be exactly that size. If you're on some weird platform that doesn't have integer types of that size then they will be undefined.
Note that it doesn't necessarily follow that sizeof(uint32_t) == 4, if CHAR_BIT != 8; again this only occurs on weird platforms.
Absolutely not, at least with regards to sizeof(uint32_t).
sizeof returns the number of bytes, not the number of bits,
and if a byte is 16 bits on the platform, sizeof(uint32_t)
will be 2, not 4; if a byte is 32 bits (and such platforms
actually exist), sizeof(uint32_t) will be 1 (and uint32_t
could be a typedef to unsigned char).
Of course, in such cases, uint8_t won't be defined.
NO, it is entirely dependent on your compiler and architecture(ie, it will give different results where you dont have integer types). If you get CHAR_BIT == 8 then yes you can rely on that. So if you are on 64bit architecture will be aligned to 64 bit boundaries same as on 32 bit architecture everything is aligned to 4 bytes.
So If the data size is critical (eg a set of bit flags) always use the fixed-size types.
Related
I was just wondering how can I know if my laptop is 64 or 32 bit machine. (it is a 64).
So, I thought about printing the following:
int main()
{
printf("%d",sizeof(int));
}
and the result was 4, which seemed weird (since it is a 64 bit machine)
But, when I printed this:
int main()
{
printf("%d",sizeof(int*));
}
the result was 8, which made more sense.
The question is:
Since I'm using a 64 bit machine, shouldn't a primitive type such as int should use 8 bytes
(64 bit) and by that sizeof int should be 8? Why isn't it so?
And why is the int* size is 8?
A bit confused here,
so thanks in advance.
No, the sizeof(int) is implementation defined, and is usually 4 bytes.
On the other hand, in order to address more than 4GB of memory (that 32bit systems can do), you need your pointers to be 8 bytes wide. int* just holds the address to "somewhere in memory", and you can't address more than 4GB of memory with just 32 bits.
Size of a pointer should be 8 byte on any 64-bit C/C++ compiler, but the same is not true for the size of int.
Wikipedia has a good explanation on that:
In many programming environments for C and C-derived languages on
64-bit machines, "int" variables are still 32 bits wide, but long
integers and pointers are 64 bits wide. These are described as having
an LP64 data model. Another alternative is the ILP64 data model in
which all three data types are 64 bits wide, and even SILP64 where
"short" integers are also 64 bits wide.[citation needed] However, in
most cases the modifications required are relatively minor and
straightforward, and many well-written programs can simply be
recompiled for the new environment without changes. Another
alternative is the LLP64 model, which maintains compatibility with
32-bit code by leaving both int and long as 32-bit. "LL" refers to the
"long long integer" type, which is at least 64 bits on all platforms,
including 32-bit environments.
The sizeof(int), sizeof(int*), and "machine size", though often correlated to each other, can each be independently smaller, the same or larger than the others. About the only C requirement is that they be at least 16 bits (or so) - other than that, it compiler dependent for the sizeof(int), sizeof(int*).
(Although maybe a pointer must be at least an int size. Hmmm)
Programmers like to have integer types of 1, 2, 4 and 8 bytes or 8, 16, 32 and 64 bits. There are only two integer types that could be smaller than int: char and short. If int was 64 bits, then you couldn't have all three of the sizes 8, 16 and 32 bits. That's why compilers tend to make int = 32 bits, so you can have char = 8 bit, short = 16 bit, int = 32 bit, long long = 64 bit and long = 32 bit or 64 bit.
Because of size_t was define as
typedef unsigned int size_t;
You should display it with %zu, %u or %lu instead of %d.
printf("%zu\n", sizet);
printf("%u\n", sizet);
printf("%lu\n", sizet);
I was wondering how to reliably determine the size of a character in a portable way. AFAIK sizeof(char) can not be used because this yields always 1, even on system where the byte has 16 bit or even more or less.
For example when dealing with bits, where you need to know exactly how big it is, I was wondering if this code would give the real size of a character, independent on what the compiler thinks of it. IMO the pointer has to be increased by the compiler to the correct size, so we should have the correct value. Am I right on this, or might there be some hidden problem with pointer arithmetics, that would yield also wrong results on some systems?
int sizeOfChar()
{
char *p = 0;
p++;
int size_of_char = (int)p;
return size_of_char;
}
There's a CHAR_BIT macro defined in <limits.h> that evaluates to exactly what its name suggests.
IMO the pointer has to be increased by the compiler to the correct size, so we should have the correct value
No, because pointer arithmetic is defined in terms of sizeof(T) (the pointer target type), and the sizeof operator yields the size in bytes. char is always exactly one byte long, so your code will always yield the NULL pointer plus one (which may not be the numerical value 1, since NULL is not required to be 0).
I think it's not clear what you consider to be "right" (or "reliable", as in the title).
Do you consider "a byte is 8 bits" to be the right answer? If so, for a platform where CHAR_BIT is 16, then you would of course get your answer by just computing:
const int octets_per_char = CHAR_BIT / 8;
No need to do pointer trickery. Also, the trickery is tricky:
On an architecture with 16 bits as the smallest addressable piece of memory, there would be 16 bits at address 0x00001, another 16 bits at address 0x0001, and so on.
So, your example would compute the result 1, since the pointer would likely be incremented from 0x0000 to 0x0001, but that doesn't seem to be what you expect it to compute.
1 I use a 16-bit address space for brevity, it makes the addresses easier to read.
The size of one char (aka byte ) in bits is determined by the macro CHAR_BIT in <limits.h> (or <climits> in C++).
The sizeof operator always returns the size of a type in bytes, not in bits.
So if on some system CHAR_BIT is 16 and sizeof(int) is 4, that means an int has 64 bits on that system.
I've just noticed an interesting property of gcc with regard to bit-fields. If I create a struct like the following:
template <int N>
struct C
{
unsigned long long data : N;
};
Then on amd64:
with -m64, for N ∊ <1, 64>, sizeof(C) == 8;
with -m32, for N ∊ <1, 32>, sizeof(C) == 4 and for N ∊ <33, 64>, sizeof(C) == 8.
(with sizeof(unsigned long long) == 8).
That seems to mostly resemble the C99/C++11 uint_fastXX_t except for the fact that on my system sizeof(uint_fast8_t) == 1. But for example, I can't reproduce anything similar with __int128 (which always results in sizeof(C) == 16).
Does it seem like a good idea to you to use the fore-mentioned struct as a «poor man's» replacement for uint_fastXX_t in C++98?
No -- a bit-field will frequently be considerably slower than a bare, unadorned int, because if you do something (e.g., addition or multiplication) that might overflow the designated size, the compiler will (typically) insert a bitwise and instruction to ensure that the result fits in the specified size. E.g., if you multiply two 10-bit numbers and put the result in a 10-bit field, the multiplication may produce up to a 20-bit number, so the compiler will normally produce the 20-bit result, the use a bitwise and to get the 10 least significant bits for the result.
Not really. On most systems we care about, uint_fast32_t, uint_least32_t, and uint32_t will be the same type.
It is only on exotic hardware the fast/least types might be 36 bits, for example, instead of 32.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
sizeof (int) == sizeof (void*)?
I was wondering whether it is guaranteed that, in both 32-bit and 64-bit systems, sizeof(int) is always equal to sizeof(void*) (i.e. 32 and 64 bits respectively).
Additionally, I need to know whether it is always guaranteed that a long int can accommodate the bits of an int and a void* together, e.g.
long int lint = (((int)integer)<<sizeof(int)) | (void*)ptr;
I was wondering whether it is guaranteed that, in both 32-bit and 64-bit systems, sizeof(int) is always equal to sizeof(void*)
No.
I need to know whether it is always guaranteed that a long int can accommodate the bits of an int and a void* together
No. A quick proof is to consider that sizeof(long int) == sizeof(int) on many modern platforms, probably including the one you're using.
The more important question is why you think you "need to know" this; the fact that you're asking such questions makes me concerned that your code is likely to be ... wobbly.
The size of an int is implementation dependent and though it may turn out to be equal to the size of a pointer in many systems, there is no guarantee.
If you decide you need code to depend on this, you can include something such as:
if (sizeof(int) != sizeof(void *))
{
fprintf(stderr, "ERROR: size assumptions are invalid; this program cannot continue.\n");
exit(-1);
}
I was wondering whether it is guaranteed that, in both 32-bit and 64-bit systems, sizeof(int) is always equal to sizeof(void*) (i.e. 32 and 64 bits respectively).
No.
Additionally, I need to know whether it is always guaranteed that a long int can accommodate the bits of an int and a void* together
No.
What you are looking for is: std::intptr_t
sizeof(std::intptr_t) == sizeof(void*)
std::intptr_t is defined as an integer of a size sufficient to hold a pointer.
Technically its optional part of the standard.
But you can usually find in the header file <cstdint> See: 18.4.1 Header <cstdint> synopsis [cstdint.syn]
Recent C99 standard provides a <stdint.h> header defining an intptr_t integral type guaranteed to have the same size as pointers.
On my Debian/AMD64/Sid, sizeof(int) is 4 bytes, but sizeof(void*) and sizeof(intptr_t) and sizeof(long) are all 8 bytes.
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).