We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Hi Guys,
I'm programing my own TCP/Ip Stack. Therefore I need structs with bitfields.
For eg:
typedef struct __attribute__ ((packed)) { uint16_t srcPort; uint16_t dstPort; uint32_t seq; uint32_t ack; unsigned headerlen : 4; unsigned res : 6; unsigned flags : 6; uint16_t hlenFlags; uint16_t windowSize; uint16_t checksum; uint16_t urgentPtr; } TCP_Header
After the bitfield variables the values aren't right anymore. Can you tell me why is this so?
Thanks for your help best regards Robert
Thanks for your help.
First of all, I have changed to uint16_t. The variables before and after the bitfield are right.
I know that bitfields aren't portable. Nevertheless I want to use them. I thnk there is an alignment problem.
I've follwing value 0x7002. According to the struct it should be:
.headerlen = 0x7 .res = 0x00 .flags = 0x02
How can I change to this order?
br Robert
But Robert, a TCP/IP stack is something you certainly want to be able to port. I mean, after all the effort...
Yeah you're right. Seems to be better to access through a 16-bit word.
But in general, how can I solve this problem? Are there specific compiler options?
The only thing you can do is change the order of the bitfields in the declaration. But the compiler will not (!) allow you full control of bit fields. A specific compiler will always follow the same rules (until possibly the rules changes when you update to the next version).
In the case of ARM compilers, ARM has specified an ABI that locks down what the compiler should do.
Are there special settings to do that?
AVR-GCC does my wanted alignment by default:
uint16_t 0x1234
struct tmp { uint16_t a : 4; //0x1 uint16_t b : 4; //0x2 uint16_t c : 4; //0x3 uint16_t d : 4; //0x4 }
Is this possible?
br robert
Man! I really didn't want to be dragged into another bit-field thread...
> I've follwing value 0x7002. According to the struct it > should be: > > .headerlen = 0x7 > .res = 0x00 > .flags = 0x02 > > How can I change to this order?
I suppose there is an endianess issue here. In little endian, lower bit field members have to be declared first.
Regards Marcus http://www.doulos.com/arm/
"I suppose there is an endianess issue here. In little endian, lower bit field members have to be declared first." Nothing so simple. 4+6+6 bits = 16. But think what happens if you want to swap the low and high byte of the container...
In the end, bit fields are problematic since the language standard never intended them to map to hardware or to a binary memory block to be transmitted raw to another machine.
To add to what Per said. Do not rely on bit fields which are ALWAYS compiler specific to work with hardware which is ALWAYS hardware specific. You will never be able to upgrade your compiler or use a different one if you do this. Read words and use bit operations as needed but use of bit fields is precarious and fraught with much configuration twiddling.
This is a feature that can't be relied on with hardware. It gets REALLY entertaining with doing floating point operations and dealing with single half and double precision data fields. That's all software and using bit fields won't work with them as 'expected'.
Stephen