Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > standard functions as macros

Reply
Thread Tools

standard functions as macros

 
 
vippstar@gmail.com
Guest
Posts: n/a
 
      01-04-2008
This question might be OT I apologise if it is.

All functions are allowed to be macros.
In a hypothetical implementation a tolower might be written as:

#define tolower(x) \
(x) == 'A' ? 'a' : \
(x) == 'B' ? 'b' : \
/* etc */
(x) == 'Z' ? 'z' : (x)

Ofcourse this has other problems (example if you pass i++ to it) but
we don't care about that now.

What I care about is 2 things:

o How does the compiler warn about incorrect arguments passed/etc?
Normally the preprocessor will change the source code, for example:

int add_one(int x);
#define add_one(x) ((x)+1)
/* ... */
char foo[2];
char * p = foo;
char * s = add_one(p); /* at this point, the compiler won't see a
'call to add_one since it would be replaced by the pp. */

o How does the macro work if I don't pass any arguments?
example:
int foo(unsigned x);
#define foo(x) (~(x))
/* ... */
int (*ptr)(void) = foo; /* how does that work? */

My tolower() macro example would not work in both cases.


thank you for your answers
 
Reply With Quote
 
 
 
 
vippstar@gmail.com
Guest
Posts: n/a
 
      01-04-2008
On Jan 4, 2:02 pm, (E-Mail Removed) wrote:
> o How does the macro work if I don't pass any arguments?
> example:
> int foo(unsigned x);
> #define foo(x) (~(x))
> /* ... */
> int (*ptr)(void) = foo; /* how does that work? */

What I ment here is int (*ptr)(int), I changed the function while I
was posting but I forgot to change ptr.
 
Reply With Quote
 
 
 
 
Richard Bos
Guest
Posts: n/a
 
      01-04-2008
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:

> All functions are allowed to be macros.


With caveats.

> In a hypothetical implementation a tolower might be written as:
>
> #define tolower(x) \
> (x) == 'A' ? 'a' : \
> (x) == 'B' ? 'b' : \
> /* etc */
> (x) == 'Z' ? 'z' : (x)
>
> Ofcourse this has other problems (example if you pass i++ to it) but
> we don't care about that now.
>
> What I care about is 2 things:
>
> o How does the compiler warn about incorrect arguments passed/etc?


Depends on the implementation

> Normally the preprocessor will change the source code, for example:
>
> int add_one(int x);
> #define add_one(x) ((x)+1)
> /* ... */
> char foo[2];
> char * p = foo;
> char * s = add_one(p); /* at this point, the compiler won't see a
> 'call to add_one since it would be replaced by the pp. */


Some implementations will remember this, and use the proper name to
complain. Some will not.

> o How does the macro work if I don't pass any arguments?
> example:
> int foo(unsigned x);
> #define foo(x) (~(x))
> /* ... */
> int (*ptr)(void) = foo; /* how does that work? */


This, at least, works: the macro foo is not the same macro as foo().

Richard
 
Reply With Quote
 
vippstar@gmail.com
Guest
Posts: n/a
 
      01-04-2008
On Jan 4, 2:18 pm, (E-Mail Removed) (Richard Bos) wrote:
> This, at least, works: the macro foo is not the same macro as foo().

Ah, this is what I had in mind too, therefore the implementation must
provide a function pointer 'x' that does the equivalent of the macro
'x()'.
Thanks for clearing this Richard.
 
Reply With Quote
 
James Kuyper
Guest
Posts: n/a
 
      01-04-2008
(E-Mail Removed) wrote:
> On Jan 4, 2:18 pm, (E-Mail Removed) (Richard Bos) wrote:
>> This, at least, works: the macro foo is not the same macro as foo().

> Ah, this is what I had in mind too, therefore the implementation must
> provide a function pointer 'x' that does the equivalent of the macro
> 'x()'.


This is explicitly required by the standard for any standard library
function implemented as a function-like macro. Note, however, that some
standard library features are explicitly described as function-like
macros, such as in <stdarg.h>. In those cases, there is no underlying
function that can be called.
 
Reply With Quote
 
Army1987
Guest
Posts: n/a
 
      01-04-2008
vippstar wrote:

> This question might be OT I apologise if it is.
>
> All functions are allowed to be macros.
> In a hypothetical implementation a tolower might be written as:
>
> #define tolower(x) \
> (x) == 'A' ? 'a' : \
> (x) == 'B' ? 'b' : \
> /* etc */
> (x) == 'Z' ? 'z' : (x)
>
> Ofcourse this has other problems (example if you pass i++ to it) but
> we don't care about that now.

No. Macro implementations are required to evaluate each argument exactly
once, and to have enough parentheses.
> What I care about is 2 things:
>
> o How does the compiler warn about incorrect arguments passed/etc?
> Normally the preprocessor will change the source code, for example:
>
> int add_one(int x);
> #define add_one(x) ((x)+1)
> /* ... */
> char foo[2];
> char * p = foo;
> char * s = add_one(p); /* at this point, the compiler won't see a
> 'call to add_one since it would be replaced by the pp. */


So what? Of course, the macro implementation of a standard library
function must have the right type, so it'd be ((int)(x)+1). So the
compiler *can* see that there's something wrong.
> o How does the macro work if I don't pass any arguments?
> example:
> int foo(unsigned x);
> #define foo(x) (~(x))
> /* ... */
> int (*ptr)(void) = foo; /* how does that work? */

The identifier foo gets replaced by the preprocessor only if immediately
followed by a ( token. ("Immediately" here includes the case in which
there is whitespace/comments between them.)

--
Army1987 (Replace "NOSPAM" with "email")
 
Reply With Quote
 
pete
Guest
Posts: n/a
 
      01-04-2008
Army1987 wrote:
>
> vippstar wrote:
>
> > This question might be OT I apologise if it is.
> >
> > All functions are allowed to be macros.
> > In a hypothetical implementation a tolower might be written as:
> >
> > #define tolower(x) \
> > (x) == 'A' ? 'a' : \
> > (x) == 'B' ? 'b' : \
> > /* etc */
> > (x) == 'Z' ? 'z' : (x)
> >
> > Ofcourse this has other problems (example if you pass i++ to it) but
> > we don't care about that now.

> No. Macro implementations are required to
> evaluate each argument exactly once,
> and to have enough parentheses.


putc and getc macros
may evaluate their stream argument more than once.

--
pete
 
Reply With Quote
 
Harald van Dijk
Guest
Posts: n/a
 
      01-04-2008
On Fri, 04 Jan 2008 17:30:07 -0500, pete wrote:
> Army1987 wrote:
>> vippstar wrote:
>> > #define tolower(x) \
>> > (x) == 'A' ? 'a' : \
>> > (x) == 'B' ? 'b' : \
>> > /* etc */
>> > (x) == 'Z' ? 'z' : (x)
>> >
>> > Ofcourse this has other problems (example if you pass i++ to it) but
>> > we don't care about that now.

>> No. Macro implementations are required to evaluate each argument
>> exactly once,
>> and to have enough parentheses.

>
> putc and getc macros
> may evaluate their stream argument more than once.


assert is a macro and may not evaluate its argument at all, depending on
NDEBUG.

But that's because special permissions or requirements are explicitly
stated. Since no such special permissions or requirements apply to
tolower, the general requirements apply, which do state each argument
must be evaluated exactly once.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
macros-loop? calling macros X times? Andrew Arro C Programming 2 07-24-2004 09:52 AM
Explanation of macros; Haskell macros mike420@ziplip.com Python 80 11-07-2003 02:22 AM
Re: Explanation of macros; Haskell macros Michael T. Babcock Python 0 11-03-2003 01:54 PM
Re: Explanation of macros; Haskell macros mike420@ziplip.com Python 5 11-01-2003 01:09 AM
Re: Explanation of macros; Haskell macros mike420@ziplip.com Python 1 10-07-2003 04:07 PM



Advertisments