Assigning "putchar" to a function pointer
Author |
Message |
Rene Herma #1 / 12
|
 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 |
|
 |
Ben Pfaf #2 / 12
|
 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 |
|
 |
Dan P #3 / 12
|
 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 |
|
 |
Eric Amic #4 / 12
|
 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 |
|
 |
Jerry Coffi #5 / 12
|
 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 |
|
 |
Rene Herma #6 / 12
|
 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 |
|
 |
Dan P #7 / 12
|
 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 |
|
 |
Hans-Bernhard Broeke #8 / 12
|
 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 |
|
 |
Lawrence Kir #9 / 12
|
 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 |
|
 |
Jonathan Leffle #10 / 12
|
 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 |
|
 |
Dan P #11 / 12
|
 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 |
|
 |
Greg Come #12 / 12
|
 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 |
|
|
|