EmbDev.net

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

Author: Francis Kong (dinosaurkfb)
Posted on:

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?
Author: Daniel G. (motello)
Posted on:

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
Author: Francis Kong (dinosaurkfb)
Posted on:

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.
Author: Daniel G. (motello)
Posted on:

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.
Author: Francis Kong (dinosaurkfb)
Posted on:

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.
Author: Clifford Slocombe (clifford)
Posted on:

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
Author: Clifford Slocombe (clifford)
Posted on:

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-bitfie...
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...

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
Author: Marcus Harnisch (Company: Doulos) (mharnisch)
Posted on:

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/
Author: Clifford Slocombe (clifford)
Posted on:

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
Author: Clifford Slocombe (clifford)
Posted on:

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/Struct...

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
Author: Marcus Harnisch (Company: Doulos) (mharnisch)
Posted on:

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.
Author: Clifford Slocombe (clifford)
Posted on:

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
Author: Marcus Harnisch (Company: Doulos) (mharnisch)
Posted on:

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/
Author: Francis Kong (dinosaurkfb)
Posted on:

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.;-)
Author: Marcus Harnisch (Company: Doulos) (mharnisch)
Posted on:

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/

Reply

Entering an e-mail address is optional. If you want to receive reply notifications by e-mail, please log in.

Rules — please read before posting

  • Post long source code as attachment, not in the text
  • Posting advertisements is forbidden.

Formatting options

  • [c]C code[/c]
  • [avrasm]AVR assembler code[/avrasm]
  • [code]code in other languages, ASCII drawings[/code]
  • [math]formula (LaTeX syntax)[/math]




Note: the original post is older than 6 months. Please don't ask any new questions in this thread, but start a new one.


webmaster@embdev.netContactAdvertising on EmbDev.net