Re: How to get certain bits from a value?
Quote:
Originally Posted by Mitsukai
im pretty sure this works 99%
MinGW 3.4.5, Borland C++ 5.5.1, Digital Mars Compiler, OpenWatcom, SCC and Turbo C++ 1 are in the bad 1% part.
Code:
#include <stdio.h>
union Packet
{
unsigned long Value;
struct
{
unsigned long T: 1;
unsigned long P: 1;
unsigned long A: 1;
unsigned long Reserved: 4;
unsigned long E: 1;
unsigned long ScanCode: 8;
unsigned long RepeatCount: 16;
} x;
};
int main() {
Packet p;
p.Value=0xFFFFFFF0UL;
printf("%lu %lu",p.x.T,p.Value>>31);
return 0;
}
With all of them, output is "0 1"
Quote:
Originally Posted by Mitsukai
its most likely this struct does not contain padding bits.
unsigned long may have padding bits.
This structure may contain padding bits between bit fields as well. I hope you know that "unsigned long T: 1" doesn't imply AT ALL that T is stored in the same unsigned long word than P, A and others...
Actually, a 16 bits machine may very well store "unsigned long" bit fields that are shorter than 16 bits, in a 16 bits word, and add padding if necessary.
For example:
struct {
unsigned long T: 3;
unsigned long P: 15;
};
On a 16 bits platform, this structure might be stored with padding... T and P being stored in two separate 16 bits words.
Similarly, sizeof(struct {unsigned long T:1;}) might very well be 1 or 2 on a 16 bits machine!
In your structure, there seems to be no place for padding between bit-fields on sensible implementations on 8 bits byte machines.
Quote:
since it only has one variable and it is an aggregate.
Wrong, it has 7 variables.
Quote:
and what do you mean with bit order?
If two bit fields are stored in the same machine byte/word/multi-word... There are mainly two sensible organisations of this fields (and a lot of other organisations which aren't sensible):
Putting the first bit-field in the lower bits (i.e. less significant bits) of the byte/word/unit and the second bit-field in the higher bits.
Of course, new issues occur because of byte order of your "unsigned long Value"!
For example, assume a 16 bits little-endian compiler, which puts T, P, A and Reserved in a first 16 bits word, with a higher-bits-to-lower-bits order of bit-fields, and put E, ScanCode and RepeatCount in the next 16 bits word... Well, in that case, the bijection of bits of bitfields to bit of unsigned long will be weird.
And, of course little-endian byte order vs big-endian byte order is not universal... There exists more complex endianess... With big-endianess in 16 bits word and little-endianess in 32 bits word.
And, padding bits in unsigned long (which may be formed of several words) as well as padding bits in simple words, may complicate things.
Padding bits isn't a myth... There exists machines without real unsigned arithmetic, on which unsigned integers are simple signed integers with the sign bit always set to zero.
On common platforms, the main issue is due to placement of bit fields.
Re: How to get certain bits from a value?
Many compilers will pad your structure to a default boundary, such as dword. Say you have a structure containing 24 bits of data, it may well be represented as sizeof(yourStruct) = 4 bytes, instead of 3. This can wreck data structures, so to fix check your compiler's #pragma options to set padding to 1 byte.
Re: How to get certain bits from a value?
i must have read wrong tutorials on bit fields.
reading this why did they even bother with bit fields.
i will do some tests myself but your explain it very well
Re: How to get certain bits from a value?
Quote:
reading this why did they even bother with bit fields.
Bit fields are great and they are safe. The issue here is not the bitfield, but the union.
(eta: Or did you mean: why did the tutorial use bitfields in that way?)
When you have written to a member of a union, you should only read from that same member. You can write to another member of the union, but then you can only read from that other member. What you cannot do safely is to write to one member of a union and then immediatly read from another member of the same union.
And using memcpy to write an integer into a bitfield has the same effect as using a union.
Re: How to get certain bits from a value?
i dont think u understand my statement..as logn as bit fields are not to be portable they are almost useless..
Re: How to get certain bits from a value?
Quote:
Originally Posted by Mitsukai
i dont think u understand my statement..as logn as bit fields are not to be portable they are almost useless..
Yes, it's true that bitfields aren't very useful.
For example, writing raw structures containing bitfields to files produce non-portable file formats. It's true to some extent for any binary data type (text formats rule :D )... But, for integer types, you can write a format portable to all 32 bits little-endian machines and with a bit of coding, these file formats can even be read on big endian and middle endian machines.
Bit fields are far from being panacea. They're seldomly useful.
But, sometimes, they can be handy and are in the language mainly because they've been in it for a long time.
Nevertheless, ABI exist (I'm not sure there exists a reliable ABI under Win32 which seems a quite bad system for binary compatibility... especially for C++) on some systems. For example, there's a System V i386 ABI which specifies how bit fields, structures and unions are layout in memory.
Re: How to get certain bits from a value?
Quote:
Originally Posted by Mitsukai
i dont think u understand my statement..as logn as bit fields are not to be portable they are almost useless..
Bitfields ARE portable (as portable as integers). In fact, bitfields in unions are also portable. What is not portable is assigning to one member of a union and then reading from another member of the same union.
:wave:
I can write the following code and it will work on all compilers:
Code:
struct BitsAndPieces
{
int a : 1;
int b : 3;
};
int f(BitsAndPieces bp)
{
return (int)(bp.a) + (int)(bp.b);
}
Re: How to get certain bits from a value?
i dont think u understand again.
that code is NOt portable, in a way u write that data in a file as binair and read the file with a diffrent compiler program then u get undefined results.
i would be very please if in C++.0x they were more standardized and forced to have the defined bit order
Re: How to get certain bits from a value?
The issue is not the compiler, but the platform portability. If you're compiling on a Intel, it'll use MSB (Most significant bit) order; whereas, if you compile to an LSB platform, like Motorola 68k, you'll find the byte ordering to be a problem ONLY if you write bit structures to a file and transfer to the other platform.
After having written code for Palm handheld (68k), this is an obvious problem that is easily solved with functions (macros, actually) that swap byte order for words and dwords.
The portability of the code we're talking about is in the person writing the code, not the compiler. In other words, the examples presented work, but when writing to file streams, just be sure to write in the same standard byte order.
Re: How to get certain bits from a value?
Quote:
Originally Posted by Mitsukai
that code is NOt portable, in a way u write that data in a file as binair and read the file with a diffrent compiler program then u get undefined results.
That is true for all structs.
Code:
struct PointAndStuff
{
int x;
int y;
short n;
};
struct Any
{
long a;
struct PointAndStuff p;
short b;
char c;
double d;
};
Each compiler can arrange the layout of the struct in a different way. Even the same compiler can give you a different struct layout if you change the type alignment option.
I do not think C/C++ guarantees that you can write any built-in type to a binary file and then correctly read it from that file using a different compiler or with different options or on a different operating system. In practice you can do testing and ensure the compiled code works, but it is not automatically guaranteed in the C/C++ standard.
But that is not what portable source code means anyway. Portable source code means: If you compile it on any compiler/machine, will the program behave the same way; like the BitsAndPieces example I gave in my earlier post.
Re: How to get certain bits from a value?
Quote:
Originally Posted by Zaccheus
I do not think C/C++ guarantees that you can write any built-in type to a binary file and then correctly read it from that file using a different compiler or with different options or on a different operating system.
Yes, byte order, and type sizes are the most common portability problems. Other problems such as byte size and uncommon value representation (padding bits, sign and magnitude vs one's complement vs two's complement) are seldom.
But, if guys want, they can draw compatibility with past and future (and present), supporting only ILP32 little-endian machines.
With bit-fields, they have to draw compatibility with different compilers of the same OS, namely Win32, because Win32 has no ABI.
On other systems, this issue doesn't appear, because they have an ABI.
I hope the C and C++ commitee will never impose any ABI break. It would reveal a very low abstraction level and would mainly imply that nobody would adopt the new standard, because compiler vendors don't want to break their OWN compatibility.
Re: How to get certain bits from a value?
Even using the same compiler, I have had problems with structs using different padding and enums having different sizes, depending on the compiler options I chose for each project. I'm now very careful to make sure all my library projects use the same settings.
Re: How to get certain bits from a value?
Quote:
Originally Posted by Zaccheus
You cannot know for certain where each field will end up inside the integer. T could be the most significant bit or the least significant bit, so could P or A.
So you cannot use a bitfield to get specific bits (eg. the least significant bit) from an integer.
:)
I can't agree on that. T could be most or least significant bit, but definitly not P or A. The byte order may vary, depending on your usage of char, int or long, but not the bit order.
Least or most significant bit may vary among compilers, but how often do you change that?
Re: How to get certain bits from a value?
a word about bitstrings beeing useful.
The major part of my life as a programmer is in transferring and processing data of telecommunication and telecontrol systems. On that level, bitstrings are extremly useful. Bits are often used to signal states of remote stations, i.e. blocked, running, reset and many others. So if you wanna no more about those states, you can use either a bitfield (once you cleared up the order), or you mask the bits out. Bitfields are much more handy - you don't have to think about mask and bit order, each and every time.
Re: How to get certain bits from a value?
Quote:
Originally Posted by Wild Thing
I can't agree on that. T could be most or least significant bit, but definitly not P or A. The byte order may vary, depending on your usage of char, int or long, but not the bit order.
Definitively?
Probably on most implementations you're aware of.
But, the standard doesn't impose any constraint on that!
An implementation may very well ignore the sign bit or do similar things.
Don't assume "all the world is two's complement with System V ABI".
Actually, writing in Packet::Value and then, reading Packet::T is undefined behavior.
Quote:
Originally Posted by C++ standard
3.10 Lvalues and rvalues [basic.lval]
15If a program attempts to access the stored value of an object through
an lvalue of other than one of the following types the behavior is
undefined25):
_________________________
25) The intent of this list is to specify those circumstances in which
--the dynamic type of the object,
--a cv-qualified version of the dynamic type of the object,
--a type that is the signed or unsigned type corresponding to the
dynamic type of the object,
--a type that is the signed or unsigned type corresponding to a cv-
qualified version of the dynamic type of the object,
--an aggregate or union type that includes one of the aforementioned
types among its members (including, recursively, a member of a sub-
aggregate or contained union),
--a type that is a (possibly cv-qualified) base class type of the
dynamic type of the object,
--a char or unsigned char type.
_________________________
an object may or may not be aliased.