I am trying to convert an unmaintainable user interface driver over to something that uses data structures to define the menu organization (This example is stripped down to the bare minimum from my actual app).
Picture an array of screens, selectable by the user's activation of some arrow keys:
Col 0 Col 1 +-----------+ Row 0 | Screen 1a | +-----------+ /\ || \/ +-----------+ +-----------+ Row 1 | Screen 2a | <===> | Screen 2b | +-----------+ +-----------+
I define a function to output each screen (in the code below, they also change the row & column indices):
void f1a(void) { outputScreen1a(); if(r > 0) r++; return; } /* ============= */ void f2a(void) { outputScreen2a(); if(c < 1) c++; return; } /* ============= */ void f2b(void) { outputScreen2b(); r = c = 0; return; }
These are called by the main() function, using a function pointer table:
static code const void (* code menuFunc[2][2])(void) = { { f1a, NULL }, { f2a, f2b } }; unsigned char r, c; void main(void) { unsigned char i; SFRPAGE = 0; /* Go to default page */ WDTCN = 0xDE; /* Disable watchdog timer */ WDTCN = 0xAD; IE = 0; /* Disable all interrupts */ i = 0; r = c = 0; while (1) { if(i < 70) { i++; } else { i = 0; (*menuFunc[r][c])(); } } /* END while (TRUE) */ } /* END main() */
As presented above, the source file will compile without error. But my application is quite a bit more complex than what I present here, the table is assymetrical (marked by the NULL pointer) and I want to guantee I do not inadvertently dereference it, so I add a qualification to the main control loop:
while (1) { if(i < 70) { i++; } else { i = 0; if((menuFunc[r][c])() != NULL) (*menuFunc[r][c])(); } } /* END while (TRUE) */
C51 does not like this. It flags the statement where I check for NULL:
?????.C:(56): error C193: '!=' : illegal conversion from/to 'void'
NULL is defined in stdio.h:
#define NULL ((void *) 0)
K&R doesn't state it explicitly, but seems to assume that void is an object type, that (void *) can only point to an object, and never uses NULL as a pointer to a function.
So the question is, if I can't use NULL to mark an uncallable function in the table, is there a null function pointer I could use instead?
============================================================ Gary Lynch | To send mail, no$pam in domain name lynchg@no$pam.com | must be changed to stacoenergy. ============================================================
Your line:
if((menuFunc[r][c])() != NULL)
contains a () making it a function call of a function taking void.
You have to realize that the deferencing * is not needed for function pointers.
Try:
if (menuFunc[r][c]) { .... }
to test your pointer.
By George, you've got it! That took care of the problem.
Thanks for the insight.
had you used a static code analyzer, you'd be saying: "By George static code analyzer, you've got it!"
:-)
By 'static code analyzer' I presume you mean PC-Lint, which prompts me to take this to the next level.
I do own a copy of PC-Lint, and have used it in the past to solve some hairy problems. I would like to use it routinely, but am impeded by the tool being apparently an attribute of the project, rather than of uV3 itself.
By that I mean every time I create a new project, I have to go tell the IDE the locations of the lint executable, the configuration file that characterizes my micro, and the compiler's default include files (all things that generally don't change--project to project).
This is about 75% of the effort of installing a new application for EVERY project (and I create a lot of them). So I only go through it if it promises me a major benefit. But I don't run into problems like the one you just witnessed very often (It looks like my last query to this body was last April).
Am I the only one who thinks we ought to be able to just install PC-Lint, enable it in uV3, and be able to run it from then on?
but you can run PC-lint from the command line, or better - using a batch file. Who needs uv3 for that...? just create "lint files" files per project, and you are in business.
lint-nt -w2 -e40 -e10 -e123 -e63 -e19 -e31 -e534 -e409 -e522 -e553 -e537 -e647 -e525 -e539 -e14 -e602 -e547 -e501 -e140 -e526 CO-RV.lnt lint_files.lnt > results.txt
and lint_files.lnt,
-I..\STR9_scheduler -I"\Keil\ARM\INC\ST\91x" -I"\Keil\ARM\RV31\INC" ..\STR9_scheduler\91x_it.c ..\STR9_scheduler\config.c ..\STR9_scheduler\LED.c ..\STR9_scheduler\main.c ..\STR9_scheduler\messaging.c ..\STR9_scheduler\priority_queue.c ..\STR9_scheduler\queue.c ..\STR9_scheduler\scheduler.c ..\STR9_scheduler\Serial.c ..\STR9_scheduler\swi_functions.c ..\STR9_scheduler\synchronization.c ..\STR9_scheduler\system_notifications.c ..\STR9_scheduler\system_services.c ..\STR9_scheduler\timer.c ..\STR9_scheduler\trace_buffer.c
View all questions in Keil forum