I need to store a value between 0-15 in C , 4 bits are enough for this. How can I just have a variable of 4 bits? Space is a开发者_开发问答 constraint here
Consider using a char
. Yeah, it's 8-bits, but you can use the bit shift operators (<<
and >>
) to store values in the other 4 bits.
Edit: Per the comments below, an unsigned char
is, in fact, preferable over char
to avoid issues with the sign bit.
You can use a bitfield to store your 4 bits, however, unless you've several of them adjacent in a struct, you won't save any space over storing the value in a byte.
You can't really have one 4-bit variable, but you can have 8-bit variables that store two 4-bit values, but you have to access them with a temp, meaning you don't save any space unless you have more than two:
uint8_t var_both;
uint8_t temp = (var_both >> 4) & 0x0F; // For first value
temp = var_both & 0x0F; // For second value
As Chris Lutz specified, you can define the amount of bits that a variable uses by adding a colon and the size of it: unsigned char myOneBitVariable:1;
and for your case 'unsigned char MyFourBitVariable:4'. I'd like to point out how extremely difficult this is and why you should avoid it.
Most modern compilers will align the space for your variables in your struct. The most general case today is 4 bytes or even 8 bytes but that varies from platform to platform and compiler to compiler. Some compilers allow you to specify the alignment of the data and its members. On GCC the keyword is __attribute__((aligned(x)))
and on MSVC it's __declspec(align(x))
. In most cases you will also need to specify how much the compiler should pack the structures. MSVC has the #pragma pack(x)
directive: http://msdn.microsoft.com/en-us/library/2e70t5y1(VS.80).aspx. You can also read about MSVC alignment here: http://msdn.microsoft.com/en-us/library/83ythb65(VS.80).aspx. GCC has its own implementation called __attribute__ ((__packed__)
, which you might have to search around for.
An example that doesn't give you what you want, using Microsoft's compiler:
#ifndef _MSC_VER
#error This alignment solution / packing solution is only valid on MSC
#endif /* ifndef _MSC_VER */
#define M_ALIGN(x) __declspec(align(x))
struct S64Bits
{
unsigned char MyOneBitVariable:1;
int My32BitInt;
};
// MSVC specific implementation of data-packing in a type.
#pragma pack(1)
struct S32Bits
{
D_ALIGN(1) int My16BitVariable:16;
D_ALIGN(1) unsigned char Padding8Bits;
D_ALIGN(1) unsigned char MyOneBitVariable1:1;
D_ALIGN(1) unsigned char MyOneBitVariable2:1;
D_ALIGN(1) unsigned char MyOneBitVariable3:1;
D_ALIGN(1) unsigned char MyOneBitVariable4:1;
D_ALIGN(1) unsigned char MyFourBitVariable:4;
};
#pragma pack(pop)
'sizeof(S64Bits)' should be 8, which it is. 'sizeof(S32Bits)' should be 4, it isn't. On msvc the latter is 6 bytes. The behavior is also compiler-specific and often have compiler-unique directives. This kind of behavior almost never gives you what you want. I often use a macro to make sure that structures that I require to be of a certain size really are:
#define TEST_TYPE_SIZE(Type, Size) assert(sizeof(Type) == Size);
That I will use below all my data-types where I try to specify the exact size of them. However, relying on a structure being any size other than sizeof(mystructure) is coding that will likely lead to difficult to debug errors. Alignment-compiler directives are best suited to be used to align data to cache-line size and similar efficiency issues.
Karl Bielefeldt provides a good natural solution of storing 4-bit values into an uint8 using bit shift operations, use those instead.
The term for a half byte is a nibble. So here:
struct two_nibbles {
unsigned a :4;
unsigned b :4;
}
You have to name your two variables x.a
and x.b
(but change x
to whatever), but you'll save a little space. You might want to check, though - I think the compiler would make sure that sizeof(struct two_nibbles) == sizeof(char)
but it might not, so you might have to add more nibbles to make it worth the space.
Are you ever going to want to take the address of the 4-bit values? If so, you need to store them in a "proper" data type, such as a char.
精彩评论