I need a two byte integer and a four byte integer. I could use a short and an int, but how I would specify such integers so as to guarantee their length?
Printable View
I need a two byte integer and a four byte integer. I could use a short and an int, but how I would specify such integers so as to guarantee their length?
First of all, a short and an int are NOT four bytes. Your only guarantee is that the size of short is smaller or equal to the size of int, and that both short and int hold at least 0 to 653535 (-32767 to 32767 if signed). That's it. In this case, it is a short and a long. But they may be longer.
Ideally, there are two solutions:
Your project has a defines.h file, that defines the macro UInt32 and UInt16 (for example), that guarantees these objects are of the type you want (by using various macros that look at the current compiler/system).
In this case, all you need to do is:
struct myShortAndIntStruct
{
UInt_16 myShort;
UInt_32 myInt;
}
I highly recommend this solution
The second solution: If you absolutely need you variables to be an exact binary length, then use a bit struct aka bit filed:
While this solution is what you are asking for, it may not be what you want.Code:struct myShortAndIntStruct
{
short int myShort : 16;
int : 0; //Anonymous member of size 0: Forces alignment of next member
long int myInt : 32;
};
Unless you are writing a driver, or are writing to a binary file, you shouldn't need variables that "are two bytes" but variables "that can hold at least two bytes". In this case, a simple short and long are what you are looking for.
A simple structure as recommended in solution 1 would be much better: A bitfield imposes varaible unpacking overhead, and since the objects are packed, it is impossible to access the variables by reference.
To add, if you must guarantee that the types are of a certain length before a compilation can be successful , a quick and dirty code snippet:
If this struct is being compiled, the code will not compile successfully if the types you chose (mytype_short and mytpe_int) are not what you expect them to be.Code:struct SizeCheck__
{
char tmp__[sizeof(mytype_short)==2?1:0];
char tmp2__[sizeof(mytype_int)==4?1:0];
};
Regards,
Paul McKenzie
While Paul's suggestion will work, it would be more obvious what's going on to do a
where static_assert is std::static_assert under the newest gcc or VS2010, or else boost::static_assert on older compilers.Code:static_assert(sizeof(int) == 4 && sizeof(short) == 2, "Types do not have expected sizes");
I would also mention that while it is not a C++ header, there is a C99 header called stdint.h which contains sized integer types.
MSVC does not have a stdint.h but here's one solution http://code.google.com/p/msinttypes/
If you only write code for Windows and use MSVC you can use the following types __int8, __int16, __int32 and __int64.
To OP, as carefully commented in the example code, the packing of these bitfields does not guarantee the alignment regardless how we instruct the compiler because it is implementation defined. Using bitfield in this case is not suitable for your need.Code:struct myShortAndIntStruct
{
short int myShort : 16;
int : 0; //Anonymous member of size 0: Forces alignment of next member
long int myInt : 32;
};
Thanks for the info. I was just trying to make a program that produced a wav file with a simple sine wave and needed specific sizes for the header and audio data. It was just a test and it worked fine with just the short and int types on my system, but i was just curious how you would go about specifying exact sizes if you needed them.
In c++, you can't demand for anything to by of any given size. At best, you can observe that something is a given size on a platform, and use that.
In your case, I would write a header like this at the top of my program:
And then, I would use the int16 and int32 types. This way, if I ever change from a 32 bit windows to a 64 bit linux, those would be the only two lines of code I would change.Code:typedef int int32; //int is 32 bits on my platform
typedef short int16; //short is 16 bits on my platform
At best, I would write a file like this:
With this, you should be able to guarantee that an object is indeed the desired size, regardless of platform/compilerCode:integer_types.h
char char_is_8_bits[CHAR_BITS==8]; //static assert that a byte is 8 bits
#ifdef windows //not actual macro
typedef long int32;
typedef short int16;
#else ifdef linux //not actual macro
typedef int int32;
typedef short int16;
#else
#error Please provide typedefs for this platform
#endif
char int32_is_4_bytes[sizeof(int32)==4]; static assert
char int16_is_2_bytes[sizeof(int16)==2]; static assert
What you want to do is serialize your struct: write/read every value one by one, given their object size (using the types as described above). WHATEVER YOU DO, don't binary write an entire struct at once! Given the different alignment of different platforms, it will not work reliably.