[LCP]Address of a label

David Spencer David.W.Spencer at oracle.com
Fri Feb 22 22:50:25 UTC 2002


> 1. This one is allowed only in GCC (it's a GNU extension):
> 
> void * ptr;
> ...
> ptr = &&label;
> ...
> goto *ptr;


Hmm.  Well, it's your code, so you can do whatever you like, but gotos 
are evil, and you should only be using them if you absolutely need to, 
which in virtually all cases you don't.  There are better ways of 
handling this situation than using a goto.


> 
> 2. This one is quite good idea, and portable too.
> 
> #define label(x) do_something ## x
> 
>    goto label(1);
> 
> do_something1:
>   ...
> do_something2:
>   ...


compare:

goto label(n)          switch (n)

do_something1:         case 1:
goto/return            break;

do_something2:         case 2:
goto/return            break;


I don't see what benefit does this have over the original switch.
It takes up just as much screen real estate, and fundamentally there's 
nothing wrong with a huge switch statement, whereas there is 
fundamentally something wrong with a goto, and you're going to have to 
have a goto at the end of each section, or a return, so you may as well 
use break.  (In fact large switches used to be the norm within Windows 
programs where you switched events, and often switched within individual 
events as well, WM_COMMAND is a good example.  The outer switch would 
process WM_COMMAND, WM_MOUSEMOVE, WM_TIMER etc, and the WM_COMMAND case 
would contain a switch for the various gadgets in a dialog box (and 
individual gadgets may require switches as well, a button for instance 
may do different things in different circumstances).)

The only disadvantage to a switch that I can think of is that I *think* 
it is implemented as an if/else if ladder, so for a switch statement 
with 200 equally probably cases you will have on average 100 comparisons 
per bytecode, which could be a little inefficient.  An optimising 
compiler might spot the fact that it is sequential and implement a 
computed goto and/or jumptable but you'd have to examine the assembler 
output to be sure.

A computed goto equivalent could be done with an array of structs:

struct bytecodes
{
   void (*func)();
} multiplexer[200];

(You can do an array of function pointers (void (*func[200])() I think) 
as well but I've struct-ed it as you may have other info pertinent to 
each function.  You don't need to store the bytecode in the structure as 
the array index corresponds to the bytecode.)

function prototypes:

void summat1();
void summat2();
void summat3();

then in a setup function:

multiplexer[0].func = summat1;
multiplexer[1].func = summat2;
multiplexer[2].func = summat3;

or multiplexer[SOME_BYTE_CODE].func... might be more readable where 
SOME_BYTE_CODE is part of an enum or something.

then in the decode

if (validate(bytecode))
{
   // this single line is where your switch/goto
   // spaghetti would have been
   (*(multiplexer[bytecode].func))();
}

This would be more efficient as the address of func would be calculated 
using ordinary array accessing code, then a simple dereference gets the 
address of the function.

Updating this code would be simple as the actual call would remain 
constant and you would only need to modify prototypes and the array 
initialiser.  Large switches are not easy to navigate.

This doesn't handle parameters of course but these could be added in a 
generic way; we don't know what these params are pointing to but the 
context - namely the fact that this is "summat1" - determines that. 
e.g. because it is summat1, param1 is a float and param2 is ignored, 
that sort of stuff.


void summat1(void *param1, void *param2);

and

void summat1(void *param1, void *param2)
{
   float theFloat = *((float*)param1);  // (float) *param1 ???
}


then call it with

(*(bytecodes[bytecode].func))((void*)&param1, (void*)&param2);


I haven't tested this, and I'd have to compile it to make sure the 
syntax is correct, but it shouldn't be far off.  I might use this idea 
for my z80 emulator...
-- 
David Spencer
www.curlypi.com




More information about the linuxCprogramming mailing list