[comp.lang.c] dereferencing function pointers

dona@ncr-fc.FtCollins.NCR.COM (Don Allingham) (01/21/89)

I've recently come across a problem with pointers to functions and pointers to
pointers to functions.  It seems as if the compiler sees no difference between
them.  For example :

===============================================================================
#include <stdio.h>

void function(s)
        char *s;
{
       (void) printf(s);
}


main()
{
        void (*pointer)();	/* pointer to function */
        void (**ppointer)();	/* pointer to pointer to function */

        pointer = function;
        ppointer = &pointer;

        (**ppointer)("hello\n");
}

===============================================================================

The above code operates as I would expect, an prints "hello" to the screen.
However, if ppointer is derefernced only once, as in the following example,
the program will produces the same results.

===============================================================================

#include <stdio.h>

void function(s)
        char *s;
{
       (void) printf(s);
}


main()
{
        void (*pointer)();
        void (**ppointer)();

        pointer = function;
        ppointer = &pointer;

        (*ppointer)("hello\n");  /* derefernced once */
}

==============================================================================

The programs run identically.  What gives?  I would think that the second
example should not run.  Am I missing something?  This occurs on both a SUN
3/60 running SunOS 4.0 and an Apollo Ageis compiler using the Berkely 4.2
option.  However, a DEC uVax running VMS 5.0.2 will not compile the program,
giving the following error messages:

----------------------------------------------------------------
                void (**pointer)();
%CC-W-CONFLICTDECL, This declaration of "pointer" conflicts
                with a previous declaration of the same name.
                At line number 12 in $DISK1:[DONA.TEST]TEST.C;2.

                ppointer = &pointer;
%CC-E-UNDECLARED, "ppointer" is not declared within the scope of
                this usage.
                At line number 15 in $DISK1:[DONA.TEST]TEST.C;2.

                ppointer = &pointer;
%CC-E-INVASSIGNTARG, Invalid target for assignment.
		At line number 15 in $DISK1:[DONA.TEST]TEST.C;2.
             
                (**ppointer)("hello\n");
%CC-E-UNDECLARED, "ppointer" is not declared within the scope of
                this usage.
                At line number 17 in $DISK1:[DONA.TEST]TEST.C;2.

        }

----------------------------------------------------------------

By the way, BOTH versions pass through lint without a complaint.

Any help would be appreciated.


==============================================================================

Don Allingham
NCR Microelectonics
Fort Collins CO, 80525
(303) 223-5100 ext. 378

gwyn@smoke.BRL.MIL (Doug Gwyn ) (01/21/89)

In article <185@ncr-fc.FtCollins.NCR.COM> dona@ncr-fc.FtCollins.NCR.COM (Don Allingham) writes:
>The above code operates as I would expect, an prints "hello" to the screen.
>However, if ppointer is derefernced only once, as in the following example,
>the program will produces the same results.

Sure, because actually functions are called through pointers to them.
The name of a function in the usual form of function call
	foo(bar);
gets immediately turned into a pointer to the function then the call
is made using that pointer.  The extra * on ppointer in your first
example of calling the function was unnecessary (but valid).

If you find the above surprising, you're not alone!

>%CC-W-CONFLICTDECL, This declaration of "pointer" conflicts
>                with a previous declaration of the same name.

All I can guess is that VMS's <stdio.h> has usurped the identifier
"pointer" to mean something else.  Perhaps it's a typedef for (void*).