This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

C51: Null function pointer

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

Parents
  • On 24-Oct-2008 05:50; Per Westermark wrote:
    >
    > I wrote a little program that extracts a bit of information
    > from the Keil project files (and also looks at the produced
    > output files).
    >
    > Then I use this to create a Makefile that uses a couple of
    > free compilers to compile (but not link) the source code
    > with suitable warning levels.
    >
    I keep digressing, but I have been trying to implement just
    what you describe for years.

    I have batch files that call Perl scripts to extract enough
    info from the *.__i and *.lnp files to create a makefile I
    could archive with my source. It would need to include the
    compile- & link-time directives (which I use for
    configuration management). I can create them for a specific
    project, but have never gotten one to work as a general
    purpose utility.

    - What language do you write in?
    - Did you get yours working for the general case?

    ============================================================
    Gary Lynch           |   To send mail, no$pam in domain name
    lynchg@no$pam.com    |   must be changed to stacoenergy.
    ============================================================
    

Reply
  • On 24-Oct-2008 05:50; Per Westermark wrote:
    >
    > I wrote a little program that extracts a bit of information
    > from the Keil project files (and also looks at the produced
    > output files).
    >
    > Then I use this to create a Makefile that uses a couple of
    > free compilers to compile (but not link) the source code
    > with suitable warning levels.
    >
    I keep digressing, but I have been trying to implement just
    what you describe for years.

    I have batch files that call Perl scripts to extract enough
    info from the *.__i and *.lnp files to create a makefile I
    could archive with my source. It would need to include the
    compile- & link-time directives (which I use for
    configuration management). I can create them for a specific
    project, but have never gotten one to work as a general
    purpose utility.

    - What language do you write in?
    - Did you get yours working for the general case?

    ============================================================
    Gary Lynch           |   To send mail, no$pam in domain name
    lynchg@no$pam.com    |   must be changed to stacoenergy.
    ============================================================
    

Children
  • I really have to check if I used C or C++ ;)

    Not the quickest way to write the string manipulation but I didn't have too much tools installed on the laptop, and I got the idea when I failed to buy a book to read while waiting for a plane after the original plane got cancelled.

    Yes, it worked quite well, but in this case I wasn't originally so very concerned about compilation options since the goal was to test-compile with other compilers. The important thing was to be able to feed the other compilers with define symbols. My aim was to use the correct set of source files, the correct include directories and the correct conditional compilation options. Then I had to do a bit of automatic tweaking of the source to get it through for example the MinGW version of the gcc compiler.

    But yes, it does pick up the command-line options that the ARM compiler prints at the top of the list files, so I can compile the files with the ARM compiler too and with the correct options.

    I basically did this instead of doing cross words, without really knowing what would come out of it.