Is sizeof(int) always equal to sizeof(void*) [duplicate] - c++

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.

Related

Why is the result of sizeof implementation defined? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
In C99, §6.5.3.4:
2 The sizeof operator yields the size (in bytes) of its operand,
which may be an expression or the parenthesized name of a type. ...
4 The value of the result is implementation-defined, and its type (an
unsigned integer type) is size_t, defined in <stddef.h> (and other
headers).
In C++14, §5.3.3:
1 The sizeof operator yields the number of bytes in the object
representation of its operand. ... The result of sizeof applied to any
other fundamental type (3.9.1) is implementation-defined.
The only guaranteed values are sizeof(char), sizeof(unsigned char) and sizeof(signed char) which is one.
However, "the number of bytes in the object representation" seems pretty iron-clad to me. For example, in C99 §6.2.6.1:
4 Values stored in non-bit-field objects of any other object type
consist of n × CHAR_BIT bits, where n is the size of an object
of that type, in bytes. ...
So why is it implementation-defined if it seems pretty defined?
Many of you seem to be misinterpretating my question. I never claimed that:
A) The size of types are defined or the same on all systems,
B) implementation-defined means it can return "random values"
What I'm getting at here is that n * CHAR_BITS is a fixed formula. The formula itself can't changed between implementations. Yes, an int may be 4 bytes or 8 bytes. I get that. But between all implementations, the value must n * CHAR_BITS.
The result of sizeof is implementation defined because the size of the various basic types are implementation defined. The only guarantees we have on the size of the types in C++ is that
sizeof(char) = 1 and sizeof(char) <= sizeof(short) <= sizeof(int) <=
sizeof(long) <= sizeof(long long)
And that each type has a minimum value it must support C11 [Annex E (informative) Implementation limits]/1
[...]The minimum magnitudes shown shall be replaced by implementation-defined magnitudes with the same sign.[...]
#define CHAR_BIT 8
#define CHAR_MAX UCHAR_MAX or SCHAR_MAX
#define CHAR_MIN 0 or SCHAR_MIN
#define INT_MAX +32767
#define INT_MIN -32767
#define LONG_MAX +2147483647
#define LONG_MIN -2147483647
#define LLONG_MAX +9223372036854775807
#define LLONG_MIN -9223372036854775807
#define MB_LEN_MAX 1
#define SCHAR_MAX +127
#define SCHAR_MIN -127
#define SHRT_MAX +32767
#define SHRT_MIN -32767
#define UCHAR_MAX 255
#define USHRT_MAX 65535
#define UINT_MAX 65535
#define ULONG_MAX 4294967295
#define ULLONG_MAX 18446744073709551615
So per the standard a int has to be able to store a number that could be stored in 16 bits but it can be bigger and on most of today's systems it is 32 bits.
What I'm getting at here is that n * CHAR_BITS is a fixed formula. The formula itself can't changed between implementations. Yes, an int may be 4 bytes or 8 bytes. I get that. But between all implementations, the value must n * CHAR_BITS.
You are correct but n is defined per C99 §6.2.6.1 as
where n is the size of an object of that type
emphasis mine
So the formula may be fixed but n is not fixed and different implementations on the same system can use a different value of n.
The result of sizeof is not implementation defined. The standard does not say that; it says:
The value of the result is implementation-defined, [...]
That is semantically different. The result of sizeof is well defined:
[...] the size (in bytes) of its operand [...]
Both the bit width of a byte in this context and the number of bytes in non char types is implementation defined.
Because the sizes of basic types are defined in terms of efficiency, not in terms of exact number of bits. An "int" must be something that the CPU can manipulate efficiently. For most modern systems, this quantity turns out to be 32 bits (or 64 bits). For older systems, it was quite often 16 bits. However, if a 35 bits CPU were to exist, an int on such a system would be 35 bits. In other words, C++ does not apply a penalty to enforce a bit-width a CPU might not support at all.
Of course, one could argue that notions of exotic bit widths for basic types have been overtaken by history. I cannot think of any modern CPU that does not support the standard set of 8, 16, and 32 bits (feel free to disagree with this statement, but at least be so kind to give an example!), and 64 bits is also pretty common (and not a big deal to support in software if hardware support is unavailable).
Arguably the C++ language has already moved away from having variable numbers of bits for char; as far as I know, u8"..." converts to char *, but the unicode specification demands that u8 is encoded in 8 bits.
If a char of 8 bits is size 1, then an int of 32 bits is size 4. If a char of 16 bits is size 1, then an int of 32 bits is only size 2. Both situations are equally valid in C++, if such sizes happen to be good choices for their respective hardware.
Padding bits are "unspecified" not "implementation-defined".
Wrong. Very, very wrong. The values of padding bytes are unspecified. The intention here is that the values of these bits may represent trap values, but not necessarily.
The standard tells you sizeof returns bytes * CHAR_BITS, but doesn't specify a size (other than the exact-width types). The number of bytes a type occupies is implementation-defined, hence sizeof must be as well.
Implementation-defined is decribed as:
unspecified value where each implementation documents how the choice
is made
When you declare a new variable in example like this:
size_t a;
it will be equal with this:
unsigned short int a; // unsigned short a
On 32-bit computers size of the integer number (int) is 4 bytes.
Size of the short int is 2 bytes.
In C programming languange 'size_t' is the return type of the 'sizeof()' operator.When you use 'sizeof()' operator he will give you the size of the object.Argument of the 'sizeof()' must be an l-value type. Size of the element(object) cannot be a negative number and it must be an integer.

Can I rely on sizeof(uint32_t) == 4?

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.

Reliably determine the size of char

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.

Does sizeof(float) always equal to sizeof(int) on all architectures?

I'm seeing code allocating memory for float using sizeof(int).
I'm wondering whether sizeof(float) always equal to sizeof(int) on all architectures?
float *pointer2Float = (float *) USER_DEFINED_MALLOC (...,..., sizeof(int))
Note: this USER_DEFINED_MALLOC isa wrapper for conventional malloc, I think.
Thanks
Regards
No, there are implementations (mainly embedded systems) with 16-bit int and 32-bit float.
And of course, the sizes are allowed to be quite different per the standard.
The sizes of ALL types (except char, signed char and unsigned char1) are implementation-defined. So it is not guaranteed that sizeof(float) will be equal to sizeof(int) on all platforms.
1. The size of char and all its variants is defined to be 1-byte by the Standard. However, the number of bits in 1-byte is implementation-defined!
No, sizeof (int) and sizeof (float) values are implementation-defined and are not guaranteed to be the same.
Here is an example of system where the two values are different:
On Cray MPP systems:
sizeof (int) is 8
sizeof (float) is 4
See here:
"Cray C/C++ Reference Manual", Table 3. Cray Research systems data type mapping in "9.1.2.2 Types"
http://docs.cray.com/books/004-2179-003/004-2179-003-manual.pdf
Also most 8-bit embedded systems have an int of 16-bit wide with sizeof (int) is 2 while floating point follow IEEE-754 and float are 32-bit with sizeof (float) of 4.
No. In C and C++, data types are platform specific. In general, this will mean:
But for other systems, the general specification is that int has the natural size suggested by the system architecture (one "word") and the four integer types char, short, int and long must each one be at least as large as the one preceding it, with char being always one byte in size. The same applies to the floating point types float, double and long double, where each one must provide at least as much precision as the preceding one.
(Taken from Data Types)
On many platforms, float and int are both often 32bit, but this isn't always the case, nor is it part of the actual specification.
There is absolutely no guarantee that sizeof (float) be equal to sizeof (int), and I'd consider the above to be a coding error.
It should use sizeof *ptrToFloat in favor of either sizeof (int) or sizeof (float).
If you are writing a multi platform that size of data type is very important, you can create an header file such as :
#define INT sizeof(int)
#define FLOAT sizeof(float)
.
.
.
It's a trick to cheat arch.

size guarantee for integral/arithmetic types in C and C++

I know that the C++ standard explicitly guarantees the size of only char, signed char and unsigned char. Also it gives guarantees that, say, short is at least as big as char, int as big as short etc. But no explicit guarantees about absolute value of, say, sizeof(int). This was the info in my head and I lived happily with it. Some time ago, however, I came across a comment in SO (can't find it) that in C long is guaranteed to be at least 4 bytes, and that requirement is "inherited" by C++. Is that the case? If so, what other implicit guarantees do we have for the sizes of arithmetic types in C++? Please note that I am absolutely not interested in practical guarantees across different platforms in this question, just theoretical ones.
18.2.2 guarantees that <climits> has the same contents as the C library header <limits.h>.
The ISO C90 standard is tricky to get hold of, which is a shame considering that C++ relies on it, but the section "Numerical limits" (numbered 2.2.4.2 in a random draft I tracked down on one occasion and have lying around) gives minimum values for the INT_MAX etc. constants in <limits.h>. For example ULONG_MAX must be at least 4294967295, from which we deduce that the width of long is at least 32 bits.
There are similar restrictions in the C99 standard, but of course those aren't the ones referenced by C++03.
This does not guarantee that long is at least 4 bytes, since in C and C++ "byte" is basically defined to mean "char", and it is not guaranteed that CHAR_BIT is 8 in C or C++. CHAR_BIT == 8 is guaranteed by both POSIX and Windows.
Don't know about C++. In C you have
Annex E
(informative)
Implementation limits
[#1] The contents of the header are given below,
in alphabetical order. The minimum magnitudes shown shall
be replaced by implementation-defined magnitudes with the
same sign. The values shall all be constant expressions
suitable for use in #if preprocessing directives. The
components are described further in 5.2.4.2.1.
#define CHAR_BIT 8
#define CHAR_MAX UCHAR_MAX or SCHAR_MAX
#define CHAR_MIN 0 or SCHAR_MIN
#define INT_MAX +32767
#define INT_MIN -32767
#define LONG_MAX +2147483647
#define LONG_MIN -2147483647
#define LLONG_MAX +9223372036854775807
#define LLONG_MIN -9223372036854775807
#define MB_LEN_MAX 1
#define SCHAR_MAX +127
#define SCHAR_MIN -127
#define SHRT_MAX +32767
#define SHRT_MIN -32767
#define UCHAR_MAX 255
#define USHRT_MAX 65535
#define UINT_MAX 65535
#define ULONG_MAX 4294967295
#define ULLONG_MAX 18446744073709551615
So char <= short <= int <= long <= long long
and
CHAR_BIT * sizeof (char) >= 8
CHAR_BIT * sizeof (short) >= 16
CHAR_BIT * size of (int) >= 16
CHAR_BIT * sizeof (long) >= 32
CHAR_BIT * sizeof (long long) >= 64
Yes, C++ type sizes are inherited from C89.
I can't find the specification right now. But it's in the Bible.
Be aware that the guaranteed ranges of these types are one less wide than on most machines:
signed char -127 ... +127 guranteed but most twos complement machines have -128 ... + 127
Likewise for the larger types.
There are several inaccuracies in what you read. These inaccuracies were either present in the source, or maybe you remembered it all incorrectly.
Firstly, a pedantic remark about one peculiar difference between C and C++. C language does not make any guarantees about the relative sizes of integer types (in bytes). C language only makes guarantees about their relative ranges. It is true that the range of int is always at least as large as the range of short and so on. However, it is formally allowed by C standard to have sizeof(short) > sizeof(int). In such case the extra bits in short would serve as padding bits, not used for value representation. Obviously, this is something that is merely allowed by the legal language in the standard, not something anyone is likely to encounter in practice.
In C++ on the other hand, the language specification makes guarantees about both the relative ranges and relative sizes of the types, so in C++ in addition to the above range relationship inherited from C it is guaranteed that sizeof(int) is greater or equal than sizeof(short).
Secondly, the C language standard guarantees minimum range for each integer type (these guarantees are present in both C and C++). Knowing the minimum range for the given type, you can always say how many value-forming bits this type is required to have (as minimum number of bits). For example, it is true that type long is required to have at least 32 value-forming bits in order to satisfy its range requirements. If you want to recalculate that into bytes, it will depend on what you understand under the term byte. If you are talking specifically about 8-bit bytes, then indeed type long will always consist of at least four 8-bit bytes. However, that does not mean that sizeof(long) is always at least 4, since in C/C++ terminology the term byte refers to char objects. char objects are not limited to 8-bits. It is quite possible to have 32-bit char type in some implementation, meaning that sizeof(long) in C/C++ bytes can legally be 1, for example.
The C standard do not explicitly say that long has to be at least 4 bytes, but they do specify a minimum range for the different integral types, which implies a minimum size.
For example, the minimum range of an unsigned long is 0 to 4,294,967,295. You need at least 32 bits to represent every single number in that range. So yes, the standard guarantee (indirectly) that a long is at least 32 bits.
C++ inherits the data types from C, so you have to go look at the C standard. The C++ standard actually references to parts of the C standard in this case.
Just be careful about the fact that some machines have chars that are more than 8 bits. For example, IIRC on the TI C5x, a long is 32 bits, but sizeof(long)==2 because chars, shorts and ints are all 16 bits with sizeof(char)==1.