Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Ok, I have checked the <strong>c99</strong> standard and can say that this is <strong>undefined behaviour</strong>.</p> <hr> <p><strong>TL;DR:</strong> It is ok to cast/convert one function pointer to another type, but if you call that function, the function types must be compatible, otherwise, you get <strong>undefined behaviour</strong>. You don't get a warning because in each step you are converting between compatible function types, but in the end, <code>helpMe</code> isn't compatible with <code>pFunc</code>.</p> <hr> <p>First of all: </p> <pre><code>char *helpMe(){ return "this is from helpMe"; } </code></pre> <p>Is valid and in C99 is the same as:</p> <pre><code>char *helpMe(void){ return "this is from helpMe"; } </code></pre> <p>From <strong>§6.7.5.3</strong> (emphasis mine):</p> <blockquote> <p>An identifier list declares only the identifiers of the parameters of the function. <strong>An empty list in a function declarator that is part of a definition of that function specifies that the function has no parameters</strong>. The empty list in a function declarator that is not part of a definition of that function specifies that no information about the number or types of the parameters is supplied.</p> </blockquote> <p>I don't know how this behaves in C89, I think that maybe, in C89 that is valid.</p> <p>On the other hand, we have: </p> <pre><code>char * (*fNewFunc)() = helpMe; </code></pre> <p>This cast is valid, because you can cast a function pointer to a function of another type and go back without problem. The compiler won't throw a warning because even their types are compatible! (void against unespecified). </p> <p>Section <strong>§6.3.2.3</strong>, paragraph 8 reads (again, emphasis mine):</p> <blockquote> <p>A pointer to a function of one type may be converted to a pointer to a function of another type and back again; the result shall compare equal to the original pointer. <strong>If a converted pointer is used to call a function whose type is not compatible with the pointed-to type, the behavior is undefined.</strong></p> </blockquote> <p>So, when you pass the pointer to <code>hearThis</code> it is casted again, from <code>char *(*)();</code> to <code>char *(*)(char *);</code> which, again, they are compatible for the compiler (thus, not throwing a warning). </p> <p><strong>BUT</strong> the standard says if the function type you are calling is incompatible with the function type pointed to, then, the <strong>behaviour is undefined</strong>.</p> <p>Te question now is, are they compatible?</p> <p>The answer is <strong>NO</strong>. if you change the type of <code>fNewFunc()</code> to <code>char *(*fNewFunc)(void);</code> you will get a warning: </p> <pre><code>p.c: In function ‘main’: p.c:12:5: warning: passing argument 1 of ‘hearThis’ from incompatible pointer type [enabled by default] p.c:6:6: note: expected ‘char * (*)(char *)’ but argument is of type ‘char * (*)(void)’ </code></pre> <p>In the standard there also says when two functions types are compatible. It is in <strong>§6.7.5.3.15</strong>. It's a bit more complicated than this :P</p> <h3>Why does it work?</h3> <p>Probably it works because the computer doesn't care. It just pushes or passes the parameters as registers, and <code>helpMe</code> just ignores them. But you should know that it is <strong>undefined behaviour</strong>.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload