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, I have this code working OK in IAR 5 kickstart and GNU toolchain:
typedef struct { uint8_t r; uint8_t g; uint8_t b; } color;
void LCD_fill(uint16_t x, uint16_t y, color fcolor) { [...]
LCD_fill(640,480,(color){0xff,0,0});
However, MDK414 gives the following errors: error: #119: cast to type "color" is not allowed error: #29: expected an expression
were the last one stays when I don't cast.
I see two issues here: 1- the impossibility to cast to the 'color' type, can be removed by adding an indirection level (but I don't want to do that for performance reasons) 2- the impossibility to use a constant structure as the parameter (I also tried defining and casting as 'const' with no success).
However, everything works OK if I define
color RED={0xff,0,0}; // or const color, btw...
and do:
LCD_fill(640,480,RED);
This looks like RealView is playing nasty on me. Any clues ?
This is not supported by the C standard. Apparently, this particular language extension is supported by gcc and IAR, but not by the RealView compiler. If you want portability, avoid non-standard code constructs. Why not simply use uint32_t for color codes and a set of macros to manipulate them?
"the impossibility to cast to the 'color' type, can be removed by adding an indirection level (but I don't want to do that for performance reasons)"
When performance is important, you should normally avoid call-by-value with a struct. In this special case, the compiler may figure out that the struct is the same size as a 32-bit processor register but the general case when sending a struct as parameter is that the compiler have to create a temporary object, and perform a copy of the data to this temporary object.
Sending pointers to structures is normally very efficient, since the ARM have many registers that can be used to store pointers and it can perform indirect addressing based on this pointer at the receiving end.
But if you look at existing code that plays with 24-bit or 32-bit colors (normal bitmap libraries etc) you'll notice that they normally makes use of a MAKE_COLOR(r,g,b) macro or similar to create a 32-bit integer value.
Thx for your comments.
I'm actually seeing the code in the simulator and (al least IAR) is packing the structure in a register and extracting the bytes from the stack one by one. However, writing 32-bit code for color is slightly faster and the compiler inlines it better; so I will switch to it.
Thanks a lot
This is not supported by the C standard.
Actually, it is. But it's a different C standard than most of us are used to.
Contrary to the OP's belief, that's not actually a cast, either. It's a compound literal, one of the things that got added to the language as of the 1999 update of the C standard: ISO/IEC 9899:1999, usually referred to as C99.
They standardized several existing extensions, and this was one of them. Others include designated initializers, // comments, complex numbers, a proper boolean type and size-specific integer types.
I confirm this. But only realview compiler don't support this because it's using register to optimize the code generated !!!! This is a big problem when you want to use code tested and compiled on an other environment
Sorry, but wrong conclusion.
Support for the feature is a question of language standards supported, and how well the standards are supported: www.keil.com/.../armccref_BABDHCGA.htm
So it has nothing at all to do with the ABI, i.e. if the compiler sends 32-bit large structures as a 32-bit integer or if it creates a temporary object and copies the values as the compiler have to do for larger structures.
Have you even tried --c99 when building your code?
Good point Per ! After adding --c99 in "Misc Controls" on "C/C++" Options, it compiles. I assumed the compiler already was in C99 mode since it didn't complain about uint*_t types (and I didn't see any fancy checkmark to enable/disable it). Should 've Please read the manual...
If you look closer you'll notice that there are not really any major compilers that "justs" support a specific standard, unless you play with --strict.
Almost all compilers brings in at least some non-controversial features from other official standards or that are much-supported on other compilers.
So most C compilers have supported // for comments long before there was a c99 standard. Just because C++ showed how extremely valuable it was with single-line comments.
This makes it hard to compile on one compiler and know that the code will also be acceptable on another compiler, unless your knowledge of the language and the language standard is good enough that you know what is part of the standard, and what is an optional extra that the compiler vendor may have added support for.
Right now, life is reasonably simple. Both C99 and C++ 2003 are old standards. But closer to the introduction of them, it was a real turmoil. Lots of compiler vendors threw in draft functionality before the standards were released just to get marketing advantages. Of course, they often misunderstood the draft - or the draft changed. Or they added features that got dropped in the final release of the standard. Lots of developers wrote code that did compile on one compiler while not on another. Either because of partial support for the new standard or incorrect implementation of the new feature.
Today, almost all compilers are almost perfectly complying, with the exception that they may drop some specific and well-defined features that may not be felt applicable for the targeted hardware.