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?
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
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.
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.
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.
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
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
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/
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
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
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.
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
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/
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.;-)
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
Log in with Google account
No account? Register here.