By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,341 Members | 1,395 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,341 IT Pros & Developers. It's quick & easy.

Is this #define legal?

P: n/a
Hi! I'm concerned about the legality of such a definition:

#define funcX funcY

where funcX belongs to the *standard* C functions. Is it legal to do
this? The standard says "any function declared in a header may be
additionally implemented as a macro defined in the header, so a library
function should not be declared explicitly if its header is included".

Is this applicable to standard functions? And, what if the definition
is outside the header where the funcY function is defined, and what if
I use it in a source file?

Thanks!

--
Sensei <se******@mac.com>

The optimist thinks this is the best of all possible worlds.
The pessimist fears it is true. [J. Robert Oppenheimer]

Aug 21 '06 #1
Share this Question
Share on Google+
19 Replies


P: n/a
Sensei wrote:
Hi! I'm concerned about the legality of such a definition:

#define funcX funcY

where funcX belongs to the *standard* C functions. Is it legal to do
this? The standard says "any function declared in a header may be
additionally implemented as a macro defined in the header, so a library
function should not be declared explicitly if its header is included".
The program may fail to compile if the appropriate header
has already #define'd funcX and your funcY does not happen to
match the existing definition perfectly. For example

#include <string.h>
#define strlen my_strlen

may fail, because <string.hmay already contain something like

size_t strlen(const char*); /* ordinary function */
#define strlen _builtin_strlen /* compiler magic */

You could avoid that potential problem:

#include <string.h>
#undef strlen /* just in case */
#define strlen my_strlen
Is this applicable to standard functions?
Yes: the section of the Standard you quoted concerns the
standard library functions.
And, what if the definition is
outside the header where the funcY function is defined, and what if I
use it in a source file?
I'm sorry; I do not understand your questions. In the first
part you seem to be talking of two different kinds of "definition,"
and I'm not sure what each refers to. "Use it in a source file" is
also confusing: First, it's not clear what "it" means, and second,
where but in a source file could you use *any* C construct?

--
Eric Sosman
es*****@acm-dot-org.invalid
--
Eric Sosman
es*****@acm-dot-org.invalid
Aug 21 '06 #2

P: n/a
Eric Sosman wrote:
Sensei wrote:
>Hi! I'm concerned about the legality of such a definition:

#define funcX funcY

where funcX belongs to the *standard* C functions. Is it legal to do
this? The standard says "any function declared in a header may be
additionally implemented as a macro defined in the header, so a library
function should not be declared explicitly if its header is included".

The program may fail to compile if the appropriate header
has already #define'd funcX and your funcY does not happen to
match the existing definition perfectly. For example

#include <string.h>
#define strlen my_strlen

may fail, because <string.hmay already contain something like

size_t strlen(const char*); /* ordinary function */
#define strlen _builtin_strlen /* compiler magic */

You could avoid that potential problem:

#include <string.h>
#undef strlen /* just in case */
#define strlen my_strlen
That's not allowed in standard C. It's covered by 7.1.3p2:
"No other identifiers are reserved. If the program declares or defines an
identifier in a context in which it is reserved (other than as allowed by
7.1.4), or defines a reserved identifier as a macro name, the behavior is
undefined."
And more practically, defining a macro with the same name as a standard
library function can break other macros which try to call the standard
function.
>Is this applicable to standard functions?

Yes: the section of the Standard you quoted concerns the
standard library functions.
>And, what if the definition is
outside the header where the funcY function is defined, and what if I
use it in a source file?

I'm sorry; I do not understand your questions. In the first
part you seem to be talking of two different kinds of "definition,"
and I'm not sure what each refers to. "Use it in a source file" is
also confusing: First, it's not clear what "it" means, and second,
where but in a source file could you use *any* C construct?
I'm confused as well, the best I can come up with is:

x1.c:
#define printf dummy
extern void printf(void);
int main(void) {
printf();
}

x2.c:
#include <stdio.h>
void dummy(void) {
puts("Hello, world!");
}

If this is meant, I don't see anything disallowing it. It's extremely poor
style, but not invalid.
Aug 21 '06 #3

P: n/a
On 2006-08-21 14:36:05 +0200, Harald van Dijk <tr*****@gmail.comsaid:
That's not allowed in standard C. It's covered by 7.1.3p2:
"No other identifiers are reserved. If the program declares or defines an
identifier in a context in which it is reserved (other than as allowed by
7.1.4), or defines a reserved identifier as a macro name, the behavior is
undefined."
And more practically, defining a macro with the same name as a standard
library function can break other macros which try to call the standard
function.
Can you clarify the statement above? Read next:
>I'm sorry; I do not understand your questions. In the first
part you seem to be talking of two different kinds of "definition,"
and I'm not sure what each refers to. "Use it in a source file" is
also confusing: First, it's not clear what "it" means, and second,
where but in a source file could you use *any* C construct?
I'm confused as well, the best I can come up with is:

x1.c:
#define printf dummy
extern void printf(void);
int main(void) {
printf();
}

x2.c:
#include <stdio.h>
void dummy(void) {
puts("Hello, world!");
}

If this is meant, I don't see anything disallowing it. It's extremely poor
style, but not invalid.
Yes, That's what I meant, using the #define inside a source file just
the way you wrote. I know it's poor, but it's what I found :)

Clarifying my concerns, I have a non standard C library that hasn't all
the functions it should, in the example code I found that since, for
instance, they have no printf or strlen, they use precompiler magic:

#include <stdio.h>

#define printf _sdk_PRINT_TO_FOO
#define strlen _sdk_STRING_LENGTH_BAR

int main(void)
{
printf("Hello, world!\n");
return 0;
}

The #defines are *inside* the application code, not in the libc. The
(pseudo)libc code has _sdk_PRINT_TO_FOO and _sdk_STRING_LENGTH_BAR
correclty (I hope) working though. I found this source quite weird, and
I didn't know about the legality of such definitions.
--
Sensei <se******@mac.com>

The optimist thinks this is the best of all possible worlds.
The pessimist fears it is true. [J. Robert Oppenheimer]

Aug 21 '06 #4

P: n/a
Sensei wrote:
Clarifying my concerns, I have a non standard C library that hasn't all
the functions it should, in the example code I found that since, for
instance, they have no printf or strlen, they use precompiler magic:

#include <stdio.h>

#define printf _sdk_PRINT_TO_FOO
#define strlen _sdk_STRING_LENGTH_BAR

int main(void)
{
printf("Hello, world!\n");
return 0;
}

The #defines are *inside* the application code, not in the libc. The
(pseudo)libc code has _sdk_PRINT_TO_FOO and _sdk_STRING_LENGTH_BAR
correclty (I hope) working though. I found this source quite weird, and
I didn't know about the legality of such definitions.
That's not allowed in standard C, but since your implementation isn't a
conforming one, it's not really relevant what the standard says, just what
works. It would probably be a good idea to hide that in a
#ifndef __STDC__ / ... / #endif
block, though.
Aug 21 '06 #5

P: n/a
Eric Sosman <es*****@acm-dot-org.invalidwrites:
Sensei wrote:
>Hi! I'm concerned about the legality of such a definition:
#define funcX funcY
where funcX belongs to the *standard* C functions. Is it legal to do
this? The standard says "any function declared in a header may be
additionally implemented as a macro defined in the header, so a
library function should not be declared explicitly if its header is
included".

The program may fail to compile if the appropriate header
has already #define'd funcX and your funcY does not happen to
match the existing definition perfectly. For example

#include <string.h>
#define strlen my_strlen

may fail, because <string.hmay already contain something like

size_t strlen(const char*); /* ordinary function */
#define strlen _builtin_strlen /* compiler magic */
A quibble: if <string.hdefined strlen as a macro, it must be a
function-like macro, such as:
#define strlen(s) _builtin_strlen(s)
so that a program can call
(strlen)(s)
to call the actual function.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Aug 21 '06 #6

P: n/a
On 2006-08-21 20:04:35 +0200, Harald van Dijk <tr*****@gmail.comsaid:
Sensei wrote:
>Clarifying my concerns, I have a non standard C library that hasn't all
the functions it should, in the example code I found that since, for
instance, they have no printf or strlen, they use precompiler magic:

#include <stdio.h>

#define printf _sdk_PRINT_TO_FOO
#define strlen _sdk_STRING_LENGTH_BAR

int main(void)
{
printf("Hello, world!\n");
return 0;
}

The #defines are *inside* the application code, not in the libc. The
(pseudo)libc code has _sdk_PRINT_TO_FOO and _sdk_STRING_LENGTH_BAR
correclty (I hope) working though. I found this source quite weird, and
I didn't know about the legality of such definitions.

That's not allowed in standard C, but since your implementation isn't a
conforming one, it's not really relevant what the standard says, just what
works. It would probably be a good idea to hide that in a
#ifndef __STDC__ / ... / #endif
block, though.
So, to make the library more standard-adherent I have to modify its
code to provide the ISO functions myself by any allowed means. Is that
right?

--
Sensei <se******@mac.com>

The optimist thinks this is the best of all possible worlds.
The pessimist fears it is true. [J. Robert Oppenheimer]

Aug 22 '06 #7

P: n/a
On 2006-08-21 22:31:54 +0200, Keith Thompson <ks***@mib.orgsaid:
A quibble: if <string.hdefined strlen as a macro, it must be a
function-like macro, such as:
#define strlen(s) _builtin_strlen(s)
so that a program can call
(strlen)(s)
to call the actual function.
Keith, a code like the following

#include <stdio.h>

#define printf _sdk_PRINT_TO_FOO
#define strlen _sdk_STRING_LENGTH_BAR

int main(void)
{
printf("Hello, world!\n");
return 0;
}

is illegal, right? See the post from Harald van Dijk.

Thanks to anyone!

--
Sensei <se******@mac.com>

The optimist thinks this is the best of all possible worlds.
The pessimist fears it is true. [J. Robert Oppenheimer]

Aug 22 '06 #8

P: n/a
Sensei <se******@mac.comwrites:
On 2006-08-21 22:31:54 +0200, Keith Thompson <ks***@mib.orgsaid:
>A quibble: if <string.hdefined strlen as a macro, it must be a
function-like macro, such as:
#define strlen(s) _builtin_strlen(s)
so that a program can call
(strlen)(s)
to call the actual function.

Keith, a code like the following

#include <stdio.h>

#define printf _sdk_PRINT_TO_FOO
#define strlen _sdk_STRING_LENGTH_BAR

int main(void)
{
printf("Hello, world!\n");
return 0;
}

is illegal, right? See the post from Harald van Dijk.
Yes, I think so, but that's not what I was talking about.

A program may not define strlen as a macro, but the implementation
(particularly the <string.hheader) is permitted to do so.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Aug 22 '06 #9

P: n/a
2006-08-21 <ln************@nuthaus.mib.org>,
Keith Thompson wrote:
Eric Sosman <es*****@acm-dot-org.invalidwrites:
>Sensei wrote:
>>Hi! I'm concerned about the legality of such a definition:
#define funcX funcY
where funcX belongs to the *standard* C functions. Is it legal to do
this? The standard says "any function declared in a header may be
additionally implemented as a macro defined in the header, so a
library function should not be declared explicitly if its header is
included".

The program may fail to compile if the appropriate header
has already #define'd funcX and your funcY does not happen to
match the existing definition perfectly. For example

#include <string.h>
#define strlen my_strlen

may fail, because <string.hmay already contain something like

size_t strlen(const char*); /* ordinary function */
#define strlen _builtin_strlen /* compiler magic */

A quibble: if <string.hdefined strlen as a macro, it must be a
function-like macro, such as:
#define strlen(s) _builtin_strlen(s)
so that a program can call
(strlen)(s)
to call the actual function.
I think it's allowed to #define strlen _builtin_strlen, provided that
_builtin_strlen is itself a real function
Aug 22 '06 #10

P: n/a
Sensei wrote:
On 2006-08-21 20:04:35 +0200, Harald van Dijk <tr*****@gmail.comsaid:
>Sensei wrote:
>>Clarifying my concerns, I have a non standard C library that hasn't all
the functions it should, in the example code I found that since, for
instance, they have no printf or strlen, they use precompiler magic:

#include <stdio.h>

#define printf _sdk_PRINT_TO_FOO
#define strlen _sdk_STRING_LENGTH_BAR

int main(void)
{
printf("Hello, world!\n");
return 0;
}

The #defines are *inside* the application code, not in the libc. The
(pseudo)libc code has _sdk_PRINT_TO_FOO and _sdk_STRING_LENGTH_BAR
correclty (I hope) working though. I found this source quite weird, and
I didn't know about the legality of such definitions.

That's not allowed in standard C, but since your implementation isn't a
conforming one, it's not really relevant what the standard says, just
what works. It would probably be a good idea to hide that in a
#ifndef __STDC__ / ... / #endif
block, though.

So, to make the library more standard-adherent I have to modify its
code to provide the ISO functions myself by any allowed means. Is that
right?
That's not what I meant, but yes, modifying the library may be another
possibility. What I meant was closer to what you originally said: keep the
#defines in the application code, except in such a way that they don't work
anymore when you switch to a conforming implementation.
Aug 22 '06 #11

P: n/a
On 2006-08-22 13:28:08 +0200, Keith Thompson <ks***@mib.orgsaid:
>#include <stdio.h>

#define printf _sdk_PRINT_TO_FOO
#define strlen _sdk_STRING_LENGTH_BAR

int main(void)
{
printf("Hello, world!\n");
return 0;
}

is illegal, right? See the post from Harald van Dijk.

Yes, I think so, but that's not what I was talking about.

A program may not define strlen as a macro, but the implementation
(particularly the <string.hheader) is permitted to do so.
My concerns is about the ISO compatibility of the statements above, and
wasn't strictly related to strlen or printf, but to all the functions
belonging to the standard.

--
Sensei <se******@mac.com>

The optimist thinks this is the best of all possible worlds.
The pessimist fears it is true. [J. Robert Oppenheimer]

Aug 22 '06 #12

P: n/a
Jordan Abel <ra****@random.yi.orgwrites:
2006-08-21 <ln************@nuthaus.mib.org>,
Keith Thompson wrote:
>Eric Sosman <es*****@acm-dot-org.invalidwrites:
>>Sensei wrote:
Hi! I'm concerned about the legality of such a definition:
#define funcX funcY
where funcX belongs to the *standard* C functions. Is it legal to do
this? The standard says "any function declared in a header may be
additionally implemented as a macro defined in the header, so a
library function should not be declared explicitly if its header is
included".

The program may fail to compile if the appropriate header
has already #define'd funcX and your funcY does not happen to
match the existing definition perfectly. For example

#include <string.h>
#define strlen my_strlen

may fail, because <string.hmay already contain something like

size_t strlen(const char*); /* ordinary function */
#define strlen _builtin_strlen /* compiler magic */

A quibble: if <string.hdefined strlen as a macro, it must be a
function-like macro, such as:
#define strlen(s) _builtin_strlen(s)
so that a program can call
(strlen)(s)
to call the actual function.

I think it's allowed to #define strlen _builtin_strlen, provided that
_builtin_strlen is itself a real function
I suppose so, but there wouldn't be much point. The implementation
could just change the name of the function from "_builtin_strlen" to
"strlen".

Unless "_builtin_strlen" is some externally defined function that
happens to implement strlen() correctly, but the author of the header
doesn't have the ability to rename it.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Aug 22 '06 #13

P: n/a
Jordan Abel wrote:
2006-08-21 <ln************@nuthaus.mib.org>,
Keith Thompson wrote:
>A quibble: if <string.hdefined strlen as a macro, it must be a
function-like macro, such as:
#define strlen(s) _builtin_strlen(s)
so that a program can call
(strlen)(s)
to call the actual function.

I think it's allowed to #define strlen _builtin_strlen, provided that
_builtin_strlen is itself a real function
It's not. You're guaranteed that stringising strlen produces "strlen" (as
long as it is not followed by an opening parenthesis).
Aug 22 '06 #14

P: n/a
Harald van Dijk <tr*****@gmail.comwrites:
Jordan Abel wrote:
>2006-08-21 <ln************@nuthaus.mib.org>,
Keith Thompson wrote:
>>A quibble: if <string.hdefined strlen as a macro, it must be a
function-like macro, such as:
#define strlen(s) _builtin_strlen(s)
so that a program can call
(strlen)(s)
to call the actual function.

I think it's allowed to #define strlen _builtin_strlen, provided that
_builtin_strlen is itself a real function

It's not. You're guaranteed that stringising strlen produces "strlen" (as
long as it is not followed by an opening parenthesis).
Where (and why) is that guaranteed?

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Aug 22 '06 #15

P: n/a
Harald van Dijk wrote:
Jordan Abel wrote:
>2006-08-21 <ln************@nuthaus.mib.org>,
Keith Thompson wrote:
>>A quibble: if <string.hdefined strlen as a macro, it must be a
function-like macro, such as:
#define strlen(s) _builtin_strlen(s)
so that a program can call
(strlen)(s)
to call the actual function.
I think it's allowed to #define strlen _builtin_strlen, provided that
_builtin_strlen is itself a real function

It's not. You're guaranteed that stringising strlen produces "strlen" (as
long as it is not followed by an opening parenthesis).
Where do you see that guarantee?

--
Clark S. Cox III
cl*******@gmail.com
Aug 22 '06 #16

P: n/a
Keith Thompson wrote:
Harald van Dijk <tr*****@gmail.comwrites:
>Jordan Abel wrote:
>>2006-08-21 <ln************@nuthaus.mib.org>,
Keith Thompson wrote:
A quibble: if <string.hdefined strlen as a macro, it must be a
function-like macro, such as:
#define strlen(s) _builtin_strlen(s)
so that a program can call
(strlen)(s)
to call the actual function.

I think it's allowed to #define strlen _builtin_strlen, provided that
_builtin_strlen is itself a real function

It's not. You're guaranteed that stringising strlen produces "strlen" (as
long as it is not followed by an opening parenthesis).

Where (and why) is that guaranteed?
By the same reason stringising xxx is guaranteed to produce "xxx": the
absense of any permission to implement it as an object-like macro. It was
mainly meant to show that the as-if rule doesn't apply. I would also be
surprised if the below code is not meant to be strictly conforming:

struct {
int strlen;
} s;
#include <string.h>
int main(void) { return s.strlen; }
Aug 22 '06 #17

P: n/a
Harald van Dijk <tr*****@gmail.comwrites:
Keith Thompson wrote:
>Harald van Dijk <tr*****@gmail.comwrites:
>>Jordan Abel wrote:
2006-08-21 <ln************@nuthaus.mib.org>,
Keith Thompson wrote:
A quibble: if <string.hdefined strlen as a macro, it must be a
function-like macro, such as:
#define strlen(s) _builtin_strlen(s)
so that a program can call
(strlen)(s)
to call the actual function.

I think it's allowed to #define strlen _builtin_strlen, provided that
_builtin_strlen is itself a real function

It's not. You're guaranteed that stringising strlen produces "strlen" (as
long as it is not followed by an opening parenthesis).

Where (and why) is that guaranteed?

By the same reason stringising xxx is guaranteed to produce "xxx": the
absense of any permission to implement it as an object-like macro. It was
mainly meant to show that the as-if rule doesn't apply. I would also be
surprised if the below code is not meant to be strictly conforming:

struct {
int strlen;
} s;
#include <string.h>
int main(void) { return s.strlen; }
I'm not entirely sure about the stringizing argument, but I find your
example much more convincing.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Aug 22 '06 #18

P: n/a
Jordan Abel <ra****@random.yi.orgwrote:
2006-08-21 <ln************@nuthaus.mib.org>,
Keith Thompson wrote:
A quibble: if <string.hdefined strlen as a macro, it must be a
function-like macro, such as:
#define strlen(s) _builtin_strlen(s)
so that a program can call
(strlen)(s)
to call the actual function.

I think it's allowed to #define strlen _builtin_strlen, provided that
_builtin_strlen is itself a real function
I don't think so. From [7.1.4]:

# Any function declared in a header may be additionally implemented as a
# function-like macro defined in the header,

Explicit mention is made of a function-like macro; no mention at all of
an object-like one; and from the same paragraph:

# Any macro definition of a function can be suppressed locally by
# enclosing the name of the function in parentheses,

Since a strictly conforming program _can_ tell the difference (using the
stringising trick at the very least), IMO a strict reading of that
paragraph disallows #defining a library function as an object-like
macro.

Richard
Aug 23 '06 #19

P: n/a
rl*@hoekstra-uitgeverij.nl (Richard Bos) writes:
Jordan Abel <ra****@random.yi.orgwrote:
>2006-08-21 <ln************@nuthaus.mib.org>,
Keith Thompson wrote:
A quibble: if <string.hdefined strlen as a macro, it must be a
function-like macro, such as:
#define strlen(s) _builtin_strlen(s)
so that a program can call
(strlen)(s)
to call the actual function.

I think it's allowed to #define strlen _builtin_strlen, provided that
_builtin_strlen is itself a real function

I don't think so. From [7.1.4]:

# Any function declared in a header may be additionally implemented as a
# function-like macro defined in the header,

Explicit mention is made of a function-like macro; no mention at all of
an object-like one; and from the same paragraph:

# Any macro definition of a function can be suppressed locally by
# enclosing the name of the function in parentheses,

Since a strictly conforming program _can_ tell the difference (using the
stringising trick at the very least), IMO a strict reading of that
paragraph disallows #defining a library function as an object-like
macro.
Even if it were legal, <string.hdeclaring strlen as an object-like
macro would be pointless. If you hae
#define strlen __builtin_strlen
(where __builtin_strlen would be the name of a function that does the
same thing), there *still* has to be a real function named "strlen",
because a program can do this:
#undef strlen
... strlen(whatever) ...

But the best argument I've seen is the code sample posted by Harald
van D??k (sorry, I'm having trouble entering accented characters):

| struct {
| int strlen;
| } s;
| #include <string.h>
| int main(void) { return s.strlen; }

If <string.hdefined strlen as an object-like macro, this strictly
conforming code would fail.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Aug 23 '06 #20

This discussion thread is closed

Replies have been disabled for this discussion.