Functions implemented as macros?

P

Pedro Graca

I wrote a pair of functions to make a string all uppercase or
lowercase.
The functions call a helper static function to do the conversion
including the address of toupper() or tolower() in the parameters.

My questions is:
Does the Standard allow toupper() or tolower() to be implemented as a
macro?
(Unlike for getc(), my documentation doesn't say they can be
implemented as macros)

To be on the safe side, should I add

#ifdef tolower
/* alternate version */
#else
/* my version */
#endif

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

This is the code I have:

#include <ctype.h>
#include <stddef.h>

static char *chg_str(char *destin, char *source, size_t n, int(f)
(int)) {
char *d = destin;
while (--n && *source) {
*destin = f(*source);
++source;
++destin;
}
*destin = 0;
return d;
}

char *lo_str(char *destin, char *source, size_t n) {
if (!source || !destin) return NULL;
if (!n) return destin;
return chg_str(destin, source, n, tolower);
}
 
J

James Kuyper

Pedro said:
I wrote a pair of functions to make a string all uppercase or
lowercase.
The functions call a helper static function to do the conversion
including the address of toupper() or tolower() in the parameters.

My questions is:
Does the Standard allow toupper() or tolower() to be implemented as a
macro?

Yes, that permission applies to all standard library functions, unless
it is specifically stated otherwise for a specific function. I found no
contrary statement in any of the obvious places for toupper() and tolower().

....
To be on the safe side, should I add

#ifdef tolower
/* alternate version */
#else
/* my version */
#endif

You don't need to get that complicated. As long as the function name is
not immediately followed by a '(' preprocessing token, it cannot be
treated as the invocation of a function-like macro; it has to be treated
as the name of the function. It will therefore decay into a pointer to
that function in most contexts, including:
 
A

Army1987

Pedro said:
I wrote a pair of functions to make a string all uppercase or
lowercase.
The functions call a helper static function to do the conversion
including the address of toupper() or tolower() in the parameters.

My questions is:
Does the Standard allow toupper() or tolower() to be implemented as a
macro?
Any function is allowed to be implemented as a macro, provided that it has
the same semantics of the function (except for getc/putc, and except for
sequence points), and that there is also a real function with that name.
To be on the safe side, should I add

#ifdef tolower
/* alternate version */
#else
/* my version */
#endif [snip]
char *lo_str(char *destin, char *source, size_t n) {
if (!source || !destin) return NULL;
if (!n) return destin;
return chg_str(destin, source, n, tolower);
When the identifier for a function-like macro isn't immediately followed
by the `(` token, it doesn't get replaced. So that tolower stays tolower,
which evaluates to the address of the extern function, regardless of
whether there is a macro with that same name. So you can be safe.
 
P

Pedro Graca

Army1987 said:
Pedro said:
My questions is:
Does the Standard allow toupper() or tolower() to be implemented as a
macro?
Any function is allowed to be implemented as a macro, provided [...]
that there is also a real function with that name.

Ah! Thank you :)
 
P

pete

James said:
Pedro Graca wrote:

Yes, that permission applies to all standard library functions, unless
it is specifically stated otherwise for a specific function.

Is it specifically stated otherwise
for any standard library functions?

I'm unaware of any exceptions.
 
J

James Kuyper

pete said:
Is it specifically stated otherwise
for any standard library functions?

I was trying to mirror the wording from 7.1.4p1: "Each of the following
statements applies unless explicitly stated otherwise in the detailed
descriptions that follow: ... Any function declared in a header may be
additionally implemented as a function-like macro defined in the header,
....".
I'm unaware of any exceptions.

There's several cases where a standard library feature is explicitly
described as being only a function-like macro, and not a function.
However, I couldn't find any examples of the reverse case: functions
where implementation as a macro was prohibited. 7.1.4p1 permits
exceptions, but there don't seem to be any.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top