From: jameskuyper@alumni.caltech.edu   
      
   On 2026-01-02 14:35, Michael Sanders wrote:   
   > On Fri, 2 Jan 2026 17:48:16 -0000 (UTC), Kaz Kylheku wrote:   
   >   
   >> On 2026-01-02, Michael Sanders wrote:   
   [restore snippage]   
   >>> void moo(char HISTORY[][64], int hst_len, int invalid, const char   
   >>> *gme_msg)   
   >>>   
   >>> void mastermind(char HISTORY[][64], int hst_len, int invalid, const   
   >>> char *gme_msg)   
   >>>   
   >>> to use either i have:   
   >>>   
   >>> void (*render)(char [][64], int, int, const char *) = MOO ? moo :   
   >>> mastermind;   
   >>>   
   >>> my multi-part question:   
   >>>   
   >>> why is void required for the function pointer?   
   ...   
   > Its void that's throwing me Kaz. I'm not sure what to think when   
   > it comes to void pointers.   
      
   The pointer named render should be declared with 'void' at the beginning   
   because moo and mastermind are declared with a 'void' at the beginning.   
      
   Consider the following alternative:   
      
   int imoo(char HISTORY[][64], int hst_len, int invalid, const char *gme_msg)   
   int imastermind(char HISTORY[][64], int hst_len, int invalid, const char   
   *gme_msg)   
      
   int (*irender)(char [][64], int, int, const char *) = MOO ? imoo :   
   imastermind;   
      
   irender requires 'int' at the beginning because imoo and imastermind   
   have 'int' at the beginning. That is the return type of the function.   
      
   The only difference is that 'void' is, in this context, a special   
   keyword indicating that the function does not return a value. Since the   
   function has no return type, it's convenient to insert 'void' in the   
   same location that would otherwise have contained the type of the value   
   returned.   
      
   Similarly, in C, the declaration "int foo()" is an old-style K&R   
   declaration that says that foo is a function that takes an unspecified   
   number of arguments of unspecified types. K&R declarations were found to   
   be too error-prone, but the language still allows them for backwards   
   compatibility. When C was first standardized, K&R declarations were   
   replace with prototype declarations which specified the type of each   
   argument, which allowed error checking.   
   The natural way for a prototype declaration to say "no arguments" would   
   have been to simply specify no arguments, and C++ uses that approach.   
   However, since C still supports the old K&R declarations, a different   
   method was used. "int foo(void)" is a function prototype that says that   
   foo doesn't take any arguments.   
      
   The third meaning for 'void' is a special meaning for pointers: "void   
   *p" declares a pointer that can store any pointer to an object.   
      
      
   > A void pointer (the pointer itself) is not of the type   
   > it points to no? ...   
      
   Of course not. In general, if the type of the thing pointed at is "X",   
   the type of the pointer itself is "pointer to X". However, a void   
   pointer has the type "pointer to void". Note: there are no void pointers   
   in your code. The pointer named render has the type "pointer to a   
   function returning void with arguments of the types ...".   
      
   > ... Its typeless & unknown at compile time   
      
   No, it very definitely has a type, "pointer to void", and if that type   
   were not known at compile time, the compiler wouldn't know what to do   
   with it. Because it does know the type, it can take the following code:   
      
   int i;   
   void *p = &i;   
      
   and translate it into machine language that creates a pointer to an int   
   which points at 'i', and converts it into a pointer to void (on many   
   systems, that conversion is a no-op, but on some machines pointers to   
   different types can have different representations) before storing it in   
   'p'.   
      
   > A 'normal' pointer in C is a variable that stores the address   
   > of another variable. And *is of the type it points to*...   
      
   No, it does not. "pointer to X" is a different type from "X".   
      
   > char str[] = "learning publicly is a humbling experience.";   
   123456789012345678901234567890   
   > char *ptr = str;   
      
   In this case, str has the type "char[   
      
   >   
   > Then void enters stage left...   
   >   
   > void *genericPointer;   
   >   
   > It can point to an integer, a character, a structure, or any other type.   
      
   It can only point at object types. It cannot point at function types.   
      
   > void *genericPointer = &intValue; void *genericPointer = str[];   
   >   
   > And it seems to survive a lack of type at compile time.   
   > Man I'm confused on this. I mean I get void is flexible,   
   > but 'void' is not void in any sense... its like a mask in some   
   > way (I'm groping for a definition) I need to study void more.   
   void* is a pointer type that can point at objects of any type. However,   
   it must be converted back to a pointer to the appropriate type before   
   the converted pointer can be used to access the object.   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   
|