EmbDev.net

Forum: ARM programming with GCC/GNU tools About using bitfield with arm-elf-gcc


von Francis K. (dinosaurkfb)


Rate this post
useful
not useful
typedef struct b_t
{
  unsigned char b0   :1;
}BT;

int a = sizeof(BT);

as defined above, when i get the size of BT, it turns out to be 4. i'm 
using arm-elf-gcc 4.1.2, and arm-elf-gcc 4.3.2 has the same result.
But when i check this value using gcc in PC linux, it is 1.
I'v turn to GCC manual, and can not find the answer.
Can anyone explain this?

von Daniel G. (motello)


Rate this post
useful
not useful
As you can see in your map-file, the size of the struct is the value 
returned by sizeof(). Your system is 32bit and normally the compiler 
aligns all variables in a struct.

Accordingly, the following struct needs 8 byte in memory.
struct {
    char a;
    int b;
} name;

If you want to remove the padding, use __attribute__((packed)):

struct {
    char a;
    int b;
}__attribute__((packed)) name;

Now the size is 5 byte.

cheers, daniel

von Francis K. (dinosaurkfb)


Rate this post
useful
not useful
Thank you very much!Problem is resolved.
I wonder, what does the difference between gcc and arm-elf-gcc come 
from, is that to say, gcc for CISC machine use default attribute 
"PACKED"? but gcc for RISC machine use default attribute not "PACKED".
Thank you again for your help.

von Daniel G. (motello)


Rate this post
useful
not useful
I have no experience with other processors. The alignment is necessary 
because the Processors often cannot access unaligned data. So, 16bit 
variables need a 2-byte alignment, char 1-byte, long 4-byte.

Packed is not default. But perhaps optimization causes that the struct 
needs only one byte. It's just a guess. Try to disable optimization and 
check the size again on your CISC machine.

Francis Kong wrote:
> Thank you very much!Problem is resolved.
> I wonder, what does the difference between gcc and arm-elf-gcc come
> from, is that to say, gcc for CISC machine use default attribute
> "PACKED"? but gcc for RISC machine use default attribute not "PACKED".
> Thank you again for your help.

von Francis K. (dinosaurkfb)


Rate this post
useful
not useful
Thank you, I checked, no optimization is default for gcc on my CISC 
maching. So i don't think optimization is the reason.
I know CISC machine can access unaligned data, while RISC can not, maybe 
that's why gcc select different ways to handle them.just a guess.

von Clifford S. (clifford)


Rate this post
useful
not useful
All bets are off when it comes to structure alignment of different 
targets. The compiler is free to do what it will with respect to the ISO 
standard, and the alignment is generally whatever is optimal (or even 
possible) on the target.

Forcing different alignment may affect performance. It may also not in 
fact reduce memory usage since any adjacent data will also be word 
aligned, so the padding will still be there, just no longer integral to 
the structure.

Structure may be useful if you need to conform to some specific data 
format, or register layout perhaps, (but be aware that not solve byte 
ordering issues), but using bitfields is not conducive to this purpose 
since the packing and ordering is also compiler dependent.

If however your use of packing is an attempt to reduce memory usage, it 
may not have the effect you expect, and it is probably a case of 
'sweating the small stuff'.

Also note that the ability to assign bitfields to any member type other 
than int is also a non-standard compiler extension.

Clifford

von Clifford S. (clifford)


Rate this post
useful
not useful
Sorry, the forum blocked me from editing my post. Additional to the 
above:


Against any perceived memory saving, consider that, since most 
architectures do not possess bit addressing features (ARM Cortex being 
an exception as it happens), it may take a lot of extra code to do the 
manipulation of bitfields. Even in architectures that have bit 
addressing, the compiler would need to support it too, by generating 
code that takes advantage of it.

Regarding the use of non-int bitfield types, things get especially 
complicated if you mix bitfield data types as can be seen in these:

http://stackoverflow.com/questions/308364/c-bitfield-packing-with-bools
http://cplus.about.com/od/learningc/ss/lowlevel_10.htm

Some general advice and information about bitfields: 
http://publications.gbdirect.co.uk/c_book/chapter6/bitfields.html

In 20 years as an embedded systems developer I can count the number of 
times I have used bitfields on one hand. There are generally too many 
compiler dependencies to make them worth using.


Clifford

von Marcus H. (mharnisch)


Rate this post
useful
not useful
I think a lot of what has been said here needs clarification.

First of all, regarding the original issue:

> typedef struct b_t
> {
>   unsigned char b0   :1;
> }BT;
>
> int a = sizeof(BT);
>
> as defined above, when i get the size of BT, it turns out to be 4.

This is just wrong for ARM targets. And both, RealView and even
CodeSourcery GCC correctly return 1.

The AAPCS (ARM Architecture Procedure Call Standard) specifies the
proper behavior in section 7.1.7: "The container type contributes to
the alignment of the containing aggregate in the same way a plain (not
bit-field) member of that type would, without exception for zero-sized
or anonymous bit-fields."

The C standard says in section 6.5.3.4 §3: "When applied to an operand
that has structure or union type, the result is the total number of
bytes in such an object, including internal and trailing padding."

In this case the unsigned char, being the only struct member, would
result in an alignment of 1 for the entire struct since there isn't
any internal or trailing padding.

Clifford wrote:
> The compiler is free to do what it will with respect to the ISO
> standard, and the alignment is generally whatever is optimal (or
> even possible) on the target.

Yes, as far as ISO is concerned. But usually, as in this case, the
AAPCS specifies the exact behavior for the target architecture.

> Structure may be useful if you need to conform to some specific data
> format, or register layout perhaps, (but be aware that not solve
> byte ordering issues), but using bitfields is not conducive to this
> purpose since the packing and ordering is also compiler dependent.

Not really. It is, at least for ARM, defined by the AAPCS. Any
compliant compiler must respect this.

> Also note that the ability to assign bitfields to any member type
> other than int is also a non-standard compiler extension.

But the ISO standard explicitly grants permission to do so:

6.7.2.1 §4 "A bit-field shall have a type that is a qualified or
unqualified version of _Bool, signed int, unsigned int, or /some other
implementation-defined type./" (emphasis added)

> Regarding the use of non-int bitfield types, things get especially
> complicated if you mix bitfield data types as can be seen in these:

Only if you if you don't spend the extra 10 minutes reading the
corresponding section(s) in the ABI.

Regards
Marcus
http://www.doulos.com/arm/

von Clifford S. (clifford)


Rate this post
useful
not useful
A standard may say anything it likes, but in the end you are building 
your code with a compiler not a standard. There are large parts of C and 
C++ that are best avoided for reason of poor or incomplete compliance or 
allowed implementation dependencies that cause code to change behaviour 
between compilers and/or architectures. In most cases it is possible to 
code portably within the language standard. I would not recommend 
attempting to code to an architecture standard, for the same reason I 
would not recommend coding in assembler. Software is too expensive to 
couple it that tightly to an architecture. It also often has longevity 
that outlives the availability of any particular architecture.

Marcus Harnisch wrote:
> This is just wrong for ARM targets. And both, RealView and even
> CodeSourcery GCC correctly return 1.
>
Padding and alignment are still 'implementation dependent' so neither 
result can be said to be wrong.

>
> The AAPCS (ARM Architecture Procedure Call Standard) specifies the
> proper behavior in section 7.1.7

That would require the compiler to be AAPCS compliant, if that is 
claimed for the compiler so be it, but it is not required by the ISO 
standard for the language, and wouldn't you rather have your code 
prtable?

It would be an unwise programmer to rely on conformance to an IP 
vendor's recommendation. That is for compiler writers to conform to if 
they so choose. Software developers would do well to code for the 
variability allowed by the language specification, rather than the 
expectations of an architecture.


> In this case the unsigned char, being the only struct member, would
> result in an alignment of 1 for the entire struct since there isn't
> any internal or trailing padding.
>
That does not follow from what the standard says. The compiler may or 
may not add padding, even in that case. As can bee seen by the example 
links I posted, it is an area where compilers vary significantly and the 
standard allows a lot of leeway. For this reason for example, the MISRA 
C standard disallows the use of bitfields

> Not really. It is, at least for ARM, defined by the AAPCS. Any
> compliant compiler must respect this.
>
It is not defined by a recognised standards authority, just an IP 
vendor. In that respect it is little more than a recommendation. Besides 
I would be interested in a precise citation that supports your point. No 
ISO compliant compiler need respect it.

> 6.7.2.1 §4 "A bit-field shall have a type that is a qualified or
> unqualified version of _Bool, signed int, unsigned int, or /some other
> implementation-defined type./" (emphasis added)
>
You are right, I should not have said it was non-standard, but rather 
not required to be supported by a compliant compiler. Given the 
reference to _Bool, it is clear that you are referencing the ISO C99; 
outside of GCC this is not a well supported standard. However since C++ 
requires support for any integral type, I concede that it would indeed 
be strange were it not supported. However C89 only allows int, signed 
int and unsigned int.



> Only if you if you don't spend the extra 10 minutes reading the
> corresponding section(s) in the ABI.

Please don't ever work on safety-critical systems! Why would you want to 
do that when it is easier and more cost effective to build portable 
code?

In the last 6 months I have worked on code for ARM, dsPIC, TI C5000, and 
x86 often on the same project. Even if I knew where all the relevant 
documentation were, or if it even existed, and I was sure that all my 
tool-chains complied to such vendor recommendations, I could not 
possibly earn a living, or get projects in on time if I had to do that, 
and I'd be doing far more work and having far more bugs that if it were 
just write portably in the first instance.

Software is expensive to write and even more expensive when it fails; it 
could cost you your job, your business, or even your life (or that of 
someone else). Therefore where possible you should avoid having to write 
it twice, and avoid having it behave differently on different platforms. 
Moreover your suggestion requires that the reader actually comprehend 
the ABI. It is a document intended for language implementers (and I 
suppose assembler programmers), not necessarily high-level language 
developers. It may not be an exemplar of great clarity, especially if it 
is not available in your native language.

I see people all the time railing against their tools claiming that they 
do not conform to this or that expectation. It is a pointless exercise 
and does not get the work done. The pragmatic programmer avoids such 
issues wherever possible by favouring those parts of the language that 
are consistently implemented across the widest range of tools and 
architectures.

Clifford

von Clifford S. (clifford)


Rate this post
useful
not useful
Francis Kong wrote:
> I'v turn to GCC manual, and can not find the answer.

In this respect, I may be eating my words w.r.t. my previous post. 
Marcus is correct in stating that it is determined by the ABI because 
that is too what the GCC manual says. I am not sure why you could not 
find the relevant page: 
http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Structures-unions-enumerations-and-bit_002dfields-implementation.html#Structures-unions-enumerations-and-bit_002dfields-implementation

Regarding my earlier assertion about char bit-fields being 
'non-standard', the manual has this to say:
--------------------------------
Allowable bit-field types other than _Bool, signed int, and unsigned int 
(C99 6.7.2.1).

No other types are permitted in strictly conforming mode.
--------------------------------

so I feel somewhat vindicated. ;-)

Suffice it to say, that if it requires that much effort to determine how 
a specific compiler should behave, it is not worth the effort, 
especially since it may not conform (either by design or implementation 
error).

Also I would suggest that you (and Marcus) need to specify the compiler 
options used to build your examples since that may also have an affect 
on the results and reproducibility of results.

Clifford

von Marcus H. (mharnisch)


Rate this post
useful
not useful
Clifford Slocombe wrote:
> That would require the compiler to be AAPCS compliant, if that is
> claimed for the compiler so be it, but it is not required by the ISO
> standard for the language,

Speaking only for the ARM architecture, I claim that offering a
non-ABI-conformant compiler is about as bad of an idea as coming up
with a creative interpretation of the C standard itself.

I suppose this is true for other architectures, too.

> and wouldn't you rather have your code prtable?

Not necessarily. My personal use of bit-fields is limited to low-level
stuff, which usually is highly unportable anyway. HW registers, page
tables, etc. Outside the HAL, I usually have no need for bit-fields. I
do know people developing SW for extremely memory constrained systems
who use bits to hold all sorts of variables.

Although I could imagine that certain communications protocol stacks
might benefit from these. OTOH, sbdy else might have written a stack
that I simply reuse, thanks to it being portable ;-)

What are your options anyway when talking bit-level stuff? Are macro
monsters and bit-level operators really more portable? Who came up
with those macros to begin with and determined the proper bit order in
their #definition? Based on which documentation? Aren't there really
pretty much the same issues to be solved that bit-fields are usually
blamed for?

This time it is my turn to provide a link:
http://c-faq.com/struct/bitfields.html

> It would be an unwise programmer to rely on conformance to an IP
> vendor's recommendation.

Please tell that to the fine people at ARM.

> That does not follow from what the standard says. The compiler may or
> may not add padding, even in that case.

Actually not (c.f. AAPCS, sec. 4.3.1)

"- The alignment of an aggregate shall be the alignment of its
most-aligned component.

- The size of an aggregate shall be the smallest multiple of its
alignment that is sufficient to hold all of its members when they are
laid out according to these rules."

> As can bee seen by the example links I posted, it is an area where
> compilers vary significantly and the standard allows a lot of
> leeway.

With all due respect, if any of these authors had the slightest clue
about how bit-fields in C are generally (not specifically!)
implemented (containers, various ways to allocate bits within the
containers, overlapping containers) there wouldn't have been that big
surprise that these guys pretended (hopefully).

I see these and other claims, such as "It is a good idea to avoid
bit-fields for efficiency" (ARM System Developer's Guide, p. 133)
which is equally silly[1], since the examples on the following pages to
back this up are completely bogus. The bit-field is accessed through a
pointer and the "more efficient" alternative ("saving of 33%") which
uses bit-wise logical operators, accesses a local variable. Guess
what, changing the example to comparing apples and apples leads to the
same code.

> Fora this reason for example, the MISRA C standard disallows the use
> of bitfields

MISRA disallows a lot of things. Therefore most close-to-metal code
contains all these exception pragmas.

> Please don't ever work on safety-critical systems!

Too late.

> Moreover your suggestion requires that the reader actually
> comprehend the ABI. It is a document intended for language
> implementers (and I suppose assembler programmers), not necessarily
> high-level language developers.

No, I suggest that if anybody decides using bit-fields they should
do their homework first.

Likewise if you nest arithmetical expressions in C, you'd better know
about internal resizing, signedness, operator precedence etc. What I
mean is, you've just got to read up on things before using them.

Whether or not anybody uses bit-fields, I could care less about. But
please don't spread any FUD.


Regards
Marcus
http://www.doulos.com/arm/

Footnotes:
[1] Otherwise I do recommend the book. It contains great solutions to
    many ARM related issues.

von Clifford S. (clifford)


Rate this post
useful
not useful
Marcus Harnisch wrote:
> Are macro monsters and bit-level operators really more portable?
In a word; yes.  For example 1<<31 will always be a correct mask for the 
most significant bit of a 32 bit word regardless of word order.

I think however, you have a point to some extent - sometimes portability 
is a pointless aim where there are other architectural constraints. For 
example, my current project is on dsPIC and the vendor supplied chip 
support headers use bit-fields extensively.The device has direct bit 
addressing instructions, so there is a potential (in fact real) 
advantage, but also this is a chip specific header, defined and supplied 
by the tool-chain vendor (Microchip in this case). I'd be wary in 
general of use of bit-fields, but never say no.

The OP's code gave no indication of being architecture specific, an the 
fact that he ran it on x86 and ARM suggests perhaps that a) it is not 
hardware specific, and b) portability may be important. That was the 
context that the advice was given.

>
> This time it is my turn to provide a link:
> http://c-faq.com/struct/bitfields.html
>
I agree with all of that. I am not against use of bit-fields, merely 
warning about any expectation the OP may have over their size and 
alignment. That was his concern and surprise, but it is not at all 
surprising, and entirely expected in so far at least that two different 
implementations on different architectures produced different results. 
The fact that you had different results for the same architecture is at 
least interesting, and may be surprising.


> MISRA disallows a lot of things. Therefore most close-to-metal code
> contains all these exception pragmas.
>
True. But to claim conformance one's code must have concession sign off 
process for each deviation. It at least makes coders think, and enforces 
peer review. Or is that hopelessly optimistic of me! ;-)

> Too late.
>
;-)


> please don't spread any FUD.
>
I would hope it was caution and wariness rather than fear and 
uncertainty. I was going to make some comment about cavalier attitude to 
portability, and putting too much trust in the compiler's conformance, 
but you made your position clear, and that is fair enough.

Now if we have finished, can we now discuss the merits of 'goto'? ;-) 
Just kidding, don't even think about it!


Clifford

von Marcus H. (mharnisch)


Rate this post
useful
not useful
Clifford Slocombe wrote:
> Marcus Harnisch wrote:
>> Are macro monsters and bit-level operators really more portable?
> In a word; yes.  For example 1<<31 will always be a correct mask for the
> most significant bit of a 32 bit word regardless of word order.

How about bit-order within a word, when an /other/-endian system is
the concern? Care to read up on what the AAPCS has to say about this
and how it all ends up on the system bus? What about hardware
registers in little endian peripherals in an otherwise big-endian
system (e.g. Cortex-M3 internal peripherals are always little-endian,
but access to the system bus can be configured to big-endian). The
compiler, of course, can only deal with either way. Are you still
absolutely sure that 1<<31 describes the bit that you were hoping it
would? Not saying it doesn't, but does it? Does your brain hurt, yet?

And no, this is not a bit (get it) easier with bit-fields, but no more
difficult either.

> The device has direct bit addressing instructions, so there is a
> potential (in fact real) advantage,

A good compiler will generate pretty much the same code for either way
to flip bits.

>> MISRA disallows a lot of things. Therefore most close-to-metal code
>> contains all these exception pragmas.
>>
> True. But to claim conformance one's code must have concession sign off
> process for each deviation. It at least makes coders think, and enforces
> peer review. Or is that hopelessly optimistic of me! ;-)

It is to some degree. After repeated warnings spit out by the lint
tool, developers end up in a loop where they hopelessly add type casts
and parentheses around sub expressions, not because it makes sense,
but to make the lint tool shut up. My MISRA compliant C code used to
look like Lisp. Sometimes (happened to me) you end up introducing bugs
because a type cast was OK from lint's perspective but wrong in the
given context. You'll always have to remind yourself that MISRA-C does
make some sense. And you can always document your deviations from
it. Like missing C99 support, a standard only 10 years old.

> Now if we have finished, can we now discuss the merits of 'goto'? ;-)
> Just kidding, don't even think about it!

So do you have anything to complain about goto? Don't get me started.

Regards
Marcus
http://www.doulos.com/arm/

von Francis K. (dinosaurkfb)


Rate this post
useful
not useful
Wow!It's like a battlefield here.;-)
Thank you, Clifford and Marcus, you had a great discussion here, your 
experiences and knowledge are a big wealth for me, and i learned a lot 
more than this subject itself include. Accept my appreciation again.;-)

von Marcus H. (mharnisch)


Rate this post
useful
not useful
Francis Kong wrote:
> Wow!It's like a battlefield here.;-)

Not at all. It was merely an enthusiastic discussion, in which Clifford 
and myself exchanged our experiences with different approaches for bit 
access.

Regards
Marcus
http://www.doulos.com/arm/

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.