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.
The Release_Notes.htm file in the ARM compiler gives an overview of changes made between MDK-ARM versions, but is there somewhere I can find out exactly what bug fixes/improvements have been made to the RealView compiler itself?
The behaviour of the compiler has changed between MDK-ARM versions 4.03a and 4.10, which is not surprising since the compiler is a new version in this release. However, this has resulted in some code developed on 4.10 (which compiles with no warnings) to fail with an error during compilation on 4.03a. Specifically I have a function which accepts a pointer to void, and am passing a function pointer to it.
I can make the code compile on both versions with some casting, but I would like to be able to see if this issue is known and if there are other issues we should be wary of.
Thank you, that is exactly the information I was after.
And thank you Per for a clear, concise and non-judgemental explanation of the issue. Hopefully this thread will be useful for others as well.
I think there is still a PC in our lab that hasn't been update with the latest compiler version, if so I will build again and make a note of the error code, but the error was about a non-compatible argument type, which certainly fits in with the references provided in this thread.
Interesting. I was not aware of the fact that casting from function pointer to void pointer is not really allowed.
A small question then:
I use something similar and want to be able to cast all function pointers to one type. Since void* is not good, can I use:
void (*) (void)
?
The specifications says that I can: c0x.coding-guidelines.com/6.3.2.3.html (766 - "A pointer to a function of one type may be converted to a pointer to a function of another type and back again")
That is exactly the type of thing I have done in the past.
Casting from a generic function pointer to a specific one as required.
Hope someone more au fait with the specifications could comment.
I use something similar and want to be able to cast all function pointers to one type.
That's allowed, but rather rarely a good idea.
Quoting C99 6.3.2.6 paragraph 8 (emphasis mine):
If a converted pointer is used to call a function whose type is not compatible with the pointed-to type, the behavior is undefined.
I.e. you must cast back to the original type before you can use the pointer, which begs the question: what could possibly have been the point of casting it in the first place?
You'll have to carry around information about the actual function type in some other way (an enum specifying one of several signatures, most likely), to know which function type to cast back to. But then you can just as well do away with the cast and keep the various types of function pointer in a union instead.
Or better still, thoroughly re-investigate the line of decisions that led to the wish to cast function pointers in the first place.
Thanks for the answer. I had seen the information in your quote, but probably should have mentioned that I do indeed always cast back.
The way I use is it as follows.
Basically, I need to initialize a table/database that contains functions to be called. For this purpose I had created a union that holds function pointers:
typedef union { void void*; void (*main) (<arguments>); int8u (*table)(<arguments>); int8u (*text) (<arguments>); } layout_fptrs_u;
I then have a struct for my table/database
typedef struct { const int8s *name; // name of the element layout_fptrs_u func; } layout_elements_t;
And the actual table itself:
layout_elements_t g_main_elements_table[] = { { "Text", sys_process_text }, { "Table", sys_process_table }, { "Title", sys_process_title }, };
The table is initialized statically, so where at first i did not have the void* member in the union and the compiler complained because the function were not necessarily of the member named 'main'. (Initializing unions always initializes using the first member-type)
So I added the void* as the first member, which worked. Now, I changed it to:
typedef union { void (*do_not_use)(void); void (*main) (<arguments>); int8u (*table)(<arguments>); int8u (*text) (<arguments>); } layout_fptrs_u; typedef void (*void_fptr_t)(void);
and the table:
layout_elements_t g_main_elements_table[] = { // Standard Elements { "Text", (void_fptr_t)sys_process_text }, { "Table", (void_fptr_t)sys_process_table }, { "Title", (void_fptr_t)sys_process_title }, };
I could have casted the fptr of the 'main' member as well though.
All I really use it for it to initialize my table. Nothing else uses the do_not_use member of the unio.
(Initializing unions always initializes using the first member-type)
As of C99, not necessarily. Among the things they added on top of C90 were named designators and non-default union initialization. So instead of this:
you could now do
layout_elements_t g_main_elements_table[] = { // Standard Elements { "Text", {.text = sys_process_text} }, { "Table", {.table = sys_process_table } }, { "Title", {.text = sys_process_title } }, };