-
September 19th, 2014, 04:59 AM
#1
Bool type problem
...
struct preferences {
bool likesMusic : 1; // Why the ' : ' sign? Is now the value of likeMucis 1 (or True) ?
bool hasHair : 1;
bool hasInternet : 1;
bool hasDinosaur : 1;
unsigned int numberOfChildren: 4;
};
....
-
September 19th, 2014, 05:16 AM
#2
Re: Bool type problem
the :1, :4 etc are specifying the number of bits that are used to store the value. So likesMusic is using 1 bit and numberOfChilden is using 4 bits. See http://msdn.microsoft.com/en-us/library/ewwyfdbe.aspx
All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!
C++23 Compiler: Microsoft VS2022 (17.6.5)
-
September 19th, 2014, 07:28 AM
#3
Re: Bool type problem
Like 2Kaud said: this is something called 'bitfields'.
Avoid using it, it is likely to cause you more headaches than it's worth.
The idea behind it is that you can use fewer bits and thus use fewer memory in your program, this could be important for very large arrays. On small low usage structs, it's sort of pointless.
While it may use less memory in storage of the data, it will use more code every time you access one of the variables. so it's a bit of a catch 22 (and one of the headaches I mentioned).
Also, do NOT use bitfields to do specific masking as there is no guarantee WHICH bits you'll be getting, compilers are free to organize this any way they see fit. (another headache issue)
In this particular sample, the struct is going to be 8 bytes. If you made the same struct without bitfields, it's also going to be 8 bytes.
So it's a pretty horribad sample of bitfields since you'll get all the disadvantages and none of the advantages.
-
September 19th, 2014, 05:46 PM
#4
Re: Bool type problem
Originally Posted by OReubens
In this particular sample, the struct is going to be 8 bytes. If you made the same struct without bitfields, it's also going to be 8 bytes.
How do you know that?
-
September 20th, 2014, 04:58 PM
#5
Re: Bool type problem
Originally Posted by razzle
How do you know that?
because it's documented to be that way. You have to find the bits and bobs from a few different places in the manual though.
Feel free to actually try it out.
-
September 21st, 2014, 01:24 AM
#6
Re: Bool type problem
Originally Posted by OReubens
because it's documented to be that way. You have to find the bits and bobs from a few different places in the manual though.
Feel free to actually try it out.
C++ is not defined by some "manual". It's defined by the C++ standard and it states that the allocation of bit-fields is implementation dependent (see 9.6 bit-fields). This means "trying out" may give different answers depending on which C++ implementation you're using.
Furthermore, the sizes of primitive types such as bool and unsigned int aren't specified by the standard either. It's also implementation dependent.
Since the OP hasn't specified a certain implementation you simply cannot know the size of the struct, neither with nor without the bit-fields.
-
September 21st, 2014, 08:25 AM
#7
Re: Bool type problem
Regardless of implementation, for a compiler adhering to the standard, you'll get (at least) 8 bytes. And yes, I DO know that.
which 4x1bit and 1x4bits you get out of the 8 bytes is however compiler dependant and potentially even compiler setting/option dependant.
There may be an oddball case out there that'll give a sizeof 16, but I can't think of any current one that will.
Well to be fair, I do have 1 compiler that'll return a size of 256, but that one doesn't really count, it's an extremely niche thing.
Now tell me you tried it, you expected 1 byte (of maybe 4) and you get 8 instead, and you can't figure out why. :-D
Last edited by OReubens; September 21st, 2014 at 08:33 AM.
-
September 22nd, 2014, 02:28 AM
#8
Re: Bool type problem
Originally Posted by OReubens
Regardless of implementation, for a compiler adhering to the standard, you'll get (at least) 8 bytes. And yes, I DO know that.
As I've shown, you have no support for that claim in the C++ standard.
You simply cannot tell the size of the struct with or without the bit-fields unless you know which exact compiler is being used.
-
September 22nd, 2014, 07:35 AM
#9
Re: Bool type problem
I do have support in the standard. Feel free to find it. Or alternatively, show me the 32-bit or higher compiler where it's less than 8.
This is actually part of the "headache" issues I pointed out already and why you're better off to avoid bitfields entirely. They just don't work the way most programmers expect them to work. And even if you do figure it out, it's still not going to be fully portable.
If you really need actual bitmasking, or packing bits into a series of bytes. do it "the hard way", don't rely on bitfields.
-
September 22nd, 2014, 07:47 AM
#10
Re: Bool type problem
Originally Posted by OReubens
I do have support in the standard. Feel free to find it.
I think the onus is on you to support your claim. razzle mentioned clause 9.6, and it reads:
Originally Posted by C++11 Clause 9.6 Paragraph 1 (part)
Allocation of bit-fields within a class object is implementation-defined. Alignment of bit-fields is implementation-defined. Bit-fields are packed into some addressable allocation unit.
Unless you show evidence to the contrary, it does seem that your claim that the standard guarantees that "the struct is going to be 8 bytes" (at least) is unfounded in this case.
Originally Posted by OReubens
Or alternatively, show me the 32-bit or higher compiler where it's less than 8.
This hints that your claim that the standard supports you "regardless of implementation" actually is false, since if you are sure that the standard mandates it, then there is no need for a "32-bit or higher compiler" stipulation.
It probably would be better to just state that for all 32-bit or higher compilers that you are aware of, the struct size is going to be at least 8 bytes. Such a claim cannot be disputed.
-
September 22nd, 2014, 09:22 AM
#11
Re: Bool type problem
The result is also highly variable on the types used.
(Visual Studio 2013)
Code:
struct preferences {
bool likesMusic : 1;
bool hasHair : 1;
bool hasInternet : 1;
bool hasDinosaur : 1;
unsigned int numberOfChildren: 4;
};
sizeof = 8
Code:
struct preferences {
char likesMusic : 1;
char hasHair : 1;
char hasInternet : 1;
char hasDinosaur : 1;
unsigned int numberOfChildren: 4;
};
sizeof = 8
Code:
struct preferences {
int likesMusic : 1;
int hasHair : 1;
int hasInternet : 1;
int hasDinosaur : 1;
int numberOfChildren: 4;
};
sizeof = 4
Code:
struct preferences {
char likesMusic : 1;
char hasHair : 1;
char hasInternet : 1;
char hasDinosaur : 1;
char numberOfChildren: 4;
};
sizeof = 1
"It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
Richard P. Feynman
-
September 22nd, 2014, 09:38 AM
#12
Re: Bool type problem
AFAIR, note that bool and enum bitfields follow special rules making OReubens claim essentially correct ( I cannot quote the std at the moment (I'm typing from a mobile device ) ) and forcing the int to be aligned on the machine natural boundary ( ie, for >=32bit this means >= 8 bytes for that struct ) ...
-
September 23rd, 2014, 08:09 AM
#13
Re: Bool type problem
Originally Posted by laserlight
This hints that your claim that the standard supports you "regardless of implementation" actually is false, since if you are sure that the standard mandates it, then there is no need for a "32-bit or higher compiler" stipulation.
This is just there because on a 16bit compiler, the size of an int will be different.
in case you want to know,
on a 16bit compiler, the sizeof will be either 4 or 6, depending on the compiler used.
that is also the exact same reason for the 'exception' I made about that one other compiler where the size will be 256 (#7) because on that particular compiler, an int is 128bytes (1024bits). yes, such beasts do exist.
It probably would be better to just state that for all 32-bit or higher compilers that you are aware of, the struct size is going to be at least 8 bytes. Such a claim cannot be disputed.
Nope, it is in the spec, but you won't find it if you only look at the specific topic about bitfields because it's not in there.
I am going to accept that I might be incorrectly interpreting the part I'm alluding to, but if so, every single C and C++ compiler I've used to date (and that's a considerable amount) seem to be interpreting that part in exactly the same way.
-
September 23rd, 2014, 08:18 AM
#14
Re: Bool type problem
Originally Posted by JohnW@Wessex
The result is also highly variable on the types used.
(Visual Studio 2013)
this is actually at the core of the reasoning. And it has everything to do with the "members of structures" and "alignment".
bitfields only accumulate into a larger type in so far as the larger type of subsequent fields is the same.
so if you have a bool bitfield, followed by a int bitfield, that's 2 distinct types, and thus the bits are not packed together.
Also note that alignment must be respected, so the int (32bit) will be 4byte aligned regardless that you only use 4 bits. so 4 bools, potentially packed into 1 byte, causes 3 padding bytes. result. 8 bytes whichever way y ou turn it.
is the headache setting in yet ?
then allow me to continue.
- It is perfectly acceptable according to the standard that a compiler entirely ignores the bitfield width and just uses separate types, each aligned and just applies clipping. there is no requirement for packing bits.
- a bool is essentially a 1bit type but has to be stored into a sizeof(char) to fulfill the requirements of type & references. A compiler is free to allow packing of bools into a char, or see a bool as a 1bit type which as a result can't be packed at all.
More if you wanna see heads exploding.
I'll just repeat myself... "avoid bitfields", there's better ways to do things.
-
September 24th, 2014, 05:47 AM
#15
Re: Bool type problem
Originally Posted by OReubens
bitfields only accumulate into a larger type in so far as the larger type of subsequent fields is the same.
so if you have a bool bitfield, followed by a int bitfield, that's 2 distinct types, and thus the bits are not packed together.
Also note that alignment must be respected, so the int (32bit) will be 4byte aligned regardless that you only use 4 bits. so 4 bools, potentially packed into 1 byte, causes 3 padding bytes. result. 8 bytes whichever way y ou turn it.
is the headache setting in yet ?
Oh wow! I had no idea!
Code:
#include <iostream>
struct S
{
int a00 : 1;
char a01 : 1;
int a02 : 1;
char a03 : 1;
int a04 : 1;
char a05 : 1;
int a06 : 1;
char a07 : 1;
int a08 : 1;
char a09 : 1;
int a10 : 1;
char a11 : 1;
int a12 : 1;
char a13 : 1;
int a14 : 1;
char a15 : 1;
int a16 : 1;
char a17 : 1;
int a18 : 1;
char a19 : 1;
};
int main()
{
std::cout << sizeof(S) << std::endl;
return 0;
}
This print 80. 80 bytes! For 20 bits!
I know for a fact nobody in my organization knows about this, and that we probably have very bloated structs in our code.
Nobody ever checks anything with static asserts...
Is your question related to IO?
Read this C++ FAQ article at parashift by Marshall Cline. In particular points 1-6.
It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|