Assigning "putchar" to a function pointer 
Author Message
 Assigning "putchar" to a function pointer

Dear everyone,

is

        int (*doprint)(int) = putchar;

safe? I seem to recall that putchar is usually implemented as a macro?
If that's the case, I would expect this to not be safe, but at the same
time I seem to have a extremely vague recollection of someone once
telling me that it's still safe.

Something about such a statement not referring to the macro when the
address is taken, but to a "real function" version? If I'm not making
any sense, please tell me. If I am, do I have the guarantee that such a
"real function implementation" will always exist in addition to a
possible macro implementation?

If I'm confusing putchar and getchar (which I know is usually a
macro), would it work for getchar?

Both libc-5.4.46 and glibc-2.2 on Linux are giving me the expected
results, without any warnings from "gcc -Wall -pedantic".

Many thanks in advance to anyone "in the know" !

Kind regards, Rene Herman
--



Sat, 20 Sep 2003 07:20:43 GMT  
 Assigning "putchar" to a function pointer

Quote:

> is

>         int (*doprint)(int) = putchar;

> safe? I seem to recall that putchar is usually implemented as a macro?

It's safe, as long as you #include <stdio.h> or declare putchar()
yourself.

Quote:
> If that's the case, I would expect this to not be safe, but at the same
> time I seem to have a extremely vague recollection of someone once
> telling me that it's still safe.

The name of a parameterized macro is only recognized as such in
an appropriate context, such as when it is followed by a left
parenthesis.  The above is not such a context, therefore it is
not a problem.

If you're still worried about it for some reason, put `#undef
putchar' above the declaration.

Quote:
> Something about such a statement not referring to the macro when the
> address is taken, but to a "real function" version? If I'm not making
> any sense, please tell me. If I am, do I have the guarantee that such a
> "real function implementation" will always exist in addition to a
> possible macro implementation?

This is guaranteed, yes.
--
"I ran it on my DeathStation 9000 and demons flew out of my nose." --Kaz


Sat, 20 Sep 2003 07:40:08 GMT  
 Assigning "putchar" to a function pointer

Quote:
>is

>        int (*doprint)(int) = putchar;

>safe?

Yup.

Quote:
>I seem to recall that putchar is usually implemented as a macro?

Even if it is, a function version *must* be present in your
implementation's libraries.

Quote:
>If that's the case, I would expect this to not be safe, but at the same
>time I seem to have a extremely vague recollection of someone once
>telling me that it's still safe.

>Something about such a statement not referring to the macro when the
>address is taken, but to a "real function" version?

Because the macro version is a parameterised macro, a plain reference to
putchar cannot refer to it.

Quote:
>If I'm confusing putchar and getchar (which I know is usually a
>macro), would it work for getchar?

It would, with the proper declaration for the pointer.

Dan
--
Dan Pop
CERN, IT Division

Mail:  CERN - IT, Bat. 31 1-014, CH-1211 Geneve 23, Switzerland



Sat, 20 Sep 2003 08:06:24 GMT  
 Assigning "putchar" to a function pointer

Quote:

> Dear everyone,

> is

>         int (*doprint)(int) = putchar;

> safe? I seem to recall that putchar is usually implemented as a macro?
> If that's the case, I would expect this to not be safe, but at the same
> time I seem to have a extremely vague recollection of someone once
> telling me that it's still safe.

> Something about such a statement not referring to the macro when the
> address is taken, but to a "real function" version? If I'm not making
> any sense, please tell me. If I am, do I have the guarantee that such a
> "real function implementation" will always exist in addition to a
> possible macro implementation?

The Standard guarantees that any standard library function with a macro
implementation also has a functional implementation as well.  In your code,
since putchar is not followed by a left paren, it cannot refer to any macro
implementation.  You are therefore referencing an actual function.

--
Eric Amick
Columbia, MD



Sat, 20 Sep 2003 08:54:06 GMT  
 Assigning "putchar" to a function pointer

says...

[ ... ]

Quote:
> I seem to recall that putchar is usually implemented as a macro?

Quite frequently, yes.  The standard explicitly gives permission for
putc and fputc to be implemented as macros; if they are, they're
allowed to evaluate arguments more than once.  IOW, arguments to putc
and fputc should not include side effects.

Quote:
> If that's the case, I would expect this to not be safe, but at the same
> time I seem to have a extremely vague recollection of someone once
> telling me that it's still safe.

Yes, that's pretty much true.  A function-like macro is only expanded
if the name is followed immediately by an open parenthesis.  When you
take the address of a function, the name is typically followed by a
semicolon instead, so the name isn't expanded.

Quote:
> If I'm confusing putchar and getchar (which I know is usually a
> macro), would it work for getchar?

It should work about the same for both.  Basically put, all the
functions are required to be implemented as functions.  There can be
a macro in addition to the function; in this case, the name followed
by an open paren (possibly separated from the name with white space)
will use the macro, but the name followed by anything else will refer
to the function.

--
    Later,
    Jerry.

The Universe is a figment of its own imagination.



Sat, 20 Sep 2003 15:12:03 GMT  
 Assigning "putchar" to a function pointer
Dear people,

a great many thanks for the clear answers, everyone! Might this, by the
way, be a good question for the C-faq? I don't know if it's really a
frequently asked question, but it would seem to fit in nicely...

Thanks all.



Sat, 20 Sep 2003 17:50:16 GMT  
 Assigning "putchar" to a function pointer

Quote:
>Quite frequently, yes.  The standard explicitly gives permission for
>putc and fputc to be implemented as macros; if they are, they're
>allowed to evaluate arguments more than once.  IOW, arguments to putc
>and fputc should not include side effects.

This applies to putc *only* and *only* to its FILE pointer argument.  
fputc, if implemented as a macro, is guaranteed to evaluate each of its
arguments once.

Dan
--
Dan Pop
CERN, IT Division

Mail:  CERN - IT, Bat. 31 1-014, CH-1211 Geneve 23, Switzerland



Sat, 20 Sep 2003 19:05:20 GMT  
 Assigning "putchar" to a function pointer

Quote:
> Dear everyone,
> is
>         int (*doprint)(int) = putchar;
> safe?

Assuming you have a suitably standard-compatible compiler: yes.

The C Standard explicitly requires all standard functions implemented
as macros, by the library, to also be available as real functions,
under the same name. You access that real function whenever you
use the function name in a way that doesn't "look like" a macro
invocation. The distinction is by appearance of an opening brace
directly after the name. I.e.:

        (putchar)('v');

always calls the real function, not the macro putchar().

The relevant wording is in paragraph 7.1.7 of the ISO C90 standard,
7.1.4 in C99. Quoting the last C99 draft:

       [...]Any
       function   declared   in   a   header  may  be  additionally
       implemented as a function-like macro defined in the  header,
       so  if  a  library  function is declared explicitly when its
       header is included, one of the techniques shown below can be
       used  to  ensure  the  declaration is not affected by such a
       macro.  Any macro definition of a function can be suppressed
       locally   by   enclosing   the   name  of  the  function  in
       parentheses, because the name is then not  followed  by  the
       left   parenthesis  that  indicates  expansion  of  a  macro
       function  name.   For  the  same  syntactic  reason,  it  is
       permitted  to take the address of a library function even if
       it is also defined as a macro.
--

Even if all the snow were burnt, ashes would remain.



Sat, 20 Sep 2003 19:38:24 GMT  
 Assigning "putchar" to a function pointer


Quote:

>says...

>[ ... ]

>> I seem to recall that putchar is usually implemented as a macro?

>Quite frequently, yes.  The standard explicitly gives permission for
>putc and fputc to be implemented as macros;

The C standard allows any standard library function to have a macro
definition in the appropriate header.

Quote:
>if they are, they're
>allowed to evaluate arguments more than once.  IOW, arguments to putc
>and fputc should not include side effects.

No, this license is given only to the putc() and getc() functions,
and only for the FILE * argument in putc().

Quote:
>> If that's the case, I would expect this to not be safe, but at the same
>> time I seem to have a extremely vague recollection of someone once
>> telling me that it's still safe.

>Yes, that's pretty much true.  A function-like macro is only expanded
>if the name is followed immediately by an open parenthesis.  When you
>take the address of a function, the name is typically followed by a
>semicolon instead, so the name isn't expanded.

There is also a "standard" way (it follows from the rule above) to call
a function directly e.g.

    (putchar)(ch);

Since putchar is not followed directly by a ( token it cannot be expanded
as a function-like macro so this guarantees a genuine function call.

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


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



Sat, 20 Sep 2003 21:53:07 GMT  
 Assigning "putchar" to a function pointer

Quote:

> is

>         int (*doprint)(int) = putchar;

> safe? I seem to recall that putchar is usually implemented as a macro?

As written, it is not safe because (as you say) it is usually a macro.
However, the standard requires that putchar be available as an actual
function, precisely so that it can be used where a pointer to function
is needed.  You can undefine putchar to ensure that the function is
visible:

#undef putchar

See P J Plauger's "The Standard C Library" for an extensive discussion
of this.  Strictly, that's for C89 and not C99, but the same will apply
pretty much the same in both.

--
Yours,

Guardian of DBD::Informix v1.00.PC1 -- http://www.perl.com/CPAN
     "I don't suffer from insanity; I enjoy every minute of it!"



Sun, 21 Sep 2003 00:44:55 GMT  
 Assigning "putchar" to a function pointer

Quote:

>> is

>>         int (*doprint)(int) = putchar;

>> safe? I seem to recall that putchar is usually implemented as a macro?

>As written, it is not safe because (as you say) it is usually a macro.
>However, the standard requires that putchar be available as an actual
>function, precisely so that it can be used where a pointer to function
>is needed.  You can undefine putchar to ensure that the function is
>visible:

>#undef putchar

>See P J Plauger's "The Standard C Library" for an extensive discussion
>of this.

Follow your own advice.  You may end up with a clue.

Dan
--
Dan Pop
CERN, IT Division

Mail:  CERN - IT, Bat. 31 1-014, CH-1211 Geneve 23, Switzerland



Sun, 21 Sep 2003 01:23:32 GMT  
 Assigning "putchar" to a function pointer


Quote:

>> is

>>         int (*doprint)(int) = putchar;

>> safe? I seem to recall that putchar is usually implemented as a macro?

>As written, it is not safe because (as you say) it is usually a macro.
>However, the standard requires that putchar be available as an actual
>function, precisely so that it can be used where a pointer to function
>is needed.  You can undefine putchar to ensure that the function is
>visible:

>#undef putchar

>See P J Plauger's "The Standard C Library" for an extensive discussion
>of this.  Strictly, that's for C89 and not C99, but the same will apply
>pretty much the same in both.

If this is so (and I agree the Standard requires what you say),
and the compiler claims to support Standard C (any one),
then what part is not safe?  And why?
--
Greg Comeau                 Comeau C/C++ 4.2.45.2 "it's so close"
ONLINE COMPILER ==>         http://www.comeaucomputing.com/tryitout
NEW: Try out libcomo!       NEW: Try out our C99 mode!



Sun, 21 Sep 2003 05:20:58 GMT  
 
 [ 12 post ] 

 Relevant Pages 

1. Assigning "putchar" to a function pointer

2. "function pointers" question

3. passing "function pointer"

4. Passing "callback" function to a function

5. Is "if (!pointer)" as portable as "if (pointer == NULL)"

6. "long pointer" vs "pointer"

7. remove() vrs fopen("""w")

8. Displaying binary data as ascii "1"'s and "0"'s

9. Looking for "Shroud"/"Obfus"

10. ""help with TSR""

11. Parse trees and "("")"

12. Error "free"-ing "malloc"-ed memory

 

 
Powered by phpBB® Forum Software