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

Inconsistent argument order in stdlib functions

P: n/a
I'm finding it really hard to keep some of these things straight...
For example, fputs is to puts as fprintf is to printf, except that
fputs has the file handle at the end and fprintf at the beginning!
Very illogical! And hard to remember.

Now this can quite easily be corrected by macros, for example:

#include <stdio.h>

#define fputs(X,Y) fputs(Y,X)

main() /* note: returning int not void!! */
{
fprintf((FILE *) stdout, "A test\n");
fputs((FILE *) stderr, "Another test\n"); /* consistency reigns! */
return 0;
}

So basically I was planning to build up a list of macro definitions to
regulate whatever inconsistencies I come through in stdlib, then I can
put them in a header to be #included in all my programs. But surely
other people will already have done this, so I thought I'd ask if any
such list is available somewhere before reinventing the wheel.

Mar 9 '07 #1
Share this Question
Share on Google+
35 Replies


P: n/a
Fr************@googlemail.com writes:
I'm finding it really hard to keep some of these things straight...
For example, fputs is to puts as fprintf is to printf, except that
fputs has the file handle at the end and fprintf at the beginning!
Very illogical! And hard to remember.
A good rule of thumb is that the FILE pointer comes last, except
for functions with a variable number of arguments, in which case
it comes first.
Now this can quite easily be corrected by macros, for example:

#include <stdio.h>

#define fputs(X,Y) fputs(Y,X)
I would recommend doing that. For one thing, the implementation
is allowed to declare a macro from each standard library
function. For another, you'll confuse any C programmer who reads
your code.
--
"Some people *are* arrogant, and others read the FAQ."
--Chris Dollin
Mar 9 '07 #2

P: n/a
Fr************@googlemail.com wrote On 03/09/07 13:24,:
I'm finding it really hard to keep some of these things straight...
For example, fputs is to puts as fprintf is to printf, except that
fputs has the file handle at the end and fprintf at the beginning!
Very illogical! And hard to remember.
Yes, it's inconsistent, but with practice you'll find
it is not hard to remember. Not for the functions you use
frequently, anyhow: I confess that despite thirty-plus years
of programming in C the order of the arguments to bsearch()
still eludes me (I scarcely ever use it), and I still get
confused about the middle two arguments to fread() and
fwrite(). But that's never bothered me much, because on
the occasions when I want to use one of these functions I
just look them up in any convenient reference: man page,
info screen, or even (gasp!) a book printed on paper. It's
not difficult.

To understand the reason for the inconsistencies, you
must realize that the C library did not spring full-armed
from the brow of Jove. It was not invented by one person,
at one place, or even at one time, but evolved over a span
of years at many places, with people borrowing ideas they'd
seen elsewhere and "improving" on them in assorted (sometimes
incompatible) ways. The library as it stands today is a
fusion of multiple different libraries with various styles
and various levels of rigor.

Evolution is like that -- or haven't you thought about
your vermiform appendix lately?
Now this can quite easily be corrected by macros, for example:

#include <stdio.h>

#define fputs(X,Y) fputs(Y,X)
You need to start with `#undef fputs' to guard against
the possibility that <stdio.hhas already defined `fputs'
as a macro.

But oh, dear Lord, sweet Jesus, don't do this, I beg!
If you simply *must* introduce macros to arrange things to
your liking, at least give them names that don't look like
something else! Your code will be completely unreadable,
and (you will discover) unreadable code tends to acquire
an unusually high density of bugs -- and then turn out to
be unmaintainable. When you write code you will be writing
in a private language nobody else understands -- and you
will also find your own ability to read the common language
diminished. If you cannot live without your silly macro,
at least have the decency to call it `BFTSPLX'.
main() /* note: returning int not void!! */
("But not for long!" -- Sweeney Todd) Under the new
"C99" version of the Standard, it is illegal to omit the
type. Typing "eye enn tee space" saves keystrokes, compared
to the comment you had to type to defend its omission.
{
fprintf((FILE *) stdout, "A test\n");
Useless cast, since `stdout' is already a `FILE*'. Or,
to put it another way, why didn't you write

fprintf((FILE *)stdout, (char*)"A test\n");
fputs((FILE *) stderr, "Another test\n"); /* consistency reigns! */
Again, `stderr' is already a `FILE*'.
return 0;
}

So basically I was planning to build up a list of macro definitions to
regulate whatever inconsistencies I come through in stdlib, then I can
put them in a header to be #included in all my programs. But surely
other people will already have done this, so I thought I'd ask if any
such list is available somewhere before reinventing the wheel.
Nobody in his right mind has done such a thing, I am sure.
Invent your wheel if you must; I am sure it will roll you
straight to Perdition.

"A foolish consistency is the hobgoblin of little minds,
Adored by little statesmen and philosophers and divines."
-- Ralph Waldo Emerson

"That leg's long enough; pull on the other."
-- Anonymous

--
Er*********@sun.com
Mar 9 '07 #3

P: n/a
Ben Pfaff wrote:
Fr************@googlemail.com writes:
<snip>
>Now this can quite easily be corrected by macros, for example:

#include <stdio.h>

#define fputs(X,Y) fputs(Y,X)

I would recommend doing that. For one thing, the implementation
is allowed to declare a macro from each standard library
function. For another, you'll confuse any C programmer who reads
your code.
Is that *wouldn't*?

--
Ioan - Ciprian Tandau
tandau _at_ freeshell _dot_ org (hope it's not too late)
(... and that it still works...)

Mar 9 '07 #4

P: n/a

"Eric Sosman" <Er*********@sun.comwrote in message
news:1173467521.93207@news1nwk...
>#define fputs(X,Y) fputs(Y,X)

You need to start with `#undef fputs' to guard against
the possibility that <stdio.hhas already defined `fputs'
as a macro.
2 questions pop up.

1. Creating a macro with the same name as an already existing function is
not undefined behaviour?
2. Is it possible for implementations to offer fputs as a macro only or must
it always be a real function too?

Mar 9 '07 #5

P: n/a
Fr************@googlemail.com writes:
I'm finding it really hard to keep some of these things straight...
For example, fputs is to puts as fprintf is to printf, except that
fputs has the file handle at the end and fprintf at the beginning!
Very illogical! And hard to remember.

Now this can quite easily be corrected by macros, for example:

#include <stdio.h>

#define fputs(X,Y) fputs(Y,X)

main() /* note: returning int not void!! */
If main returns int (which it does), you should say so. Implicit int
was never a particularly good idea, and it's been removed from the
language in C99. Declare it as:

int main(void)
{
fprintf((FILE *) stdout, "A test\n");
stdout is already of type FILE*. There's no need to cast it.

*Most* casts are unnecessary.
fputs((FILE *) stderr, "Another test\n"); /* consistency reigns! */
return 0;
}

So basically I was planning to build up a list of macro definitions to
regulate whatever inconsistencies I come through in stdlib, then I can
put them in a header to be #included in all my programs. But surely
other people will already have done this, so I thought I'd ask if any
such list is available somewhere before reinventing the wheel.
You can do that if you really want to, but *please* don't redefine the
standard functions with the same names. Anyone reading your code
who has managed to learn the correct order of the arguments to fputs()
is going to see your
fputs(stderr, "Another test\n");
and be convinced that it's an error. For that matter, I think that
redefining standard function names like this invokes undefined
behavior.

If you really want to do this, pick your own names, preferably with a
unique prefix.

I'm not sure anyone has bothered to do this, and I suspect it's
because most programmers don't think it's necesssary. A programmer
who's experienced enough to implement such a set of macros most likely
has gotten used to the odd parameter orderings and either has
memorized them or keeps a reference book at hand to look them up when
necessary. Another common way to avoid the confusion is to use just,
say, printf() and fprintf() rather than fputs:

fprintf(stderr, "Another test\n");
fprintf(stderr, "%s\n", message);

This has some cost in performance, but that's usually not significant.

--
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."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Mar 9 '07 #6

P: n/a
Servé Laurijssen wrote On 03/09/07 14:48,:
"Eric Sosman" <Er*********@sun.comwrote in message
news:1173467521.93207@news1nwk...
>>>#define fputs(X,Y) fputs(Y,X)

You need to start with `#undef fputs' to guard against
the possibility that <stdio.hhas already defined `fputs'
as a macro.

2 questions pop up.

1. Creating a macro with the same name as an already existing function is
not undefined behaviour?
No. It may look at first like an infinite recursion,
but macros are not expanded recursively. That is, if the
expansion of macro M generates another appearance of M,
directly or indirectly, the generated M is not treated as
a macro.
2. Is it possible for implementations to offer fputs as a macro only ormust
it always be a real function too?
It must be provided as a real function, primarily so
that you can aim a function pointer at it:

#include <stdio.h>
int (*fptr)(const char *, FILE *) = fputs;
...
fptr("Hello, world!\n", stdout);

This is the case with most things in the Standard library;
a very few (like assert(), for example) are required to be
macros and only macros.

However, the implementation is allowed to provide macros
for any of the Standard "real functions" that it likes. This
is usually done in the name of efficiency: putc(), for example,
is frequently implemented as a macro expanding to in-line code
that usually avoids the overhead of a function call. Some
implementations use special macros for some of the mathematical
and string-bashing functions; <math.hmight contain something
along the lines of

double sqrt(double);
#define sqrt(x) __emit_sqrt_instruction_in_code__(x)

... thus providing both an ordinary function you can point at
with a function pointer, and a (presumably) fast alternative
for in-line use.

--
Er*********@sun.com
Mar 9 '07 #7

P: n/a
Nelu <sp*******@gmail.comwrites:
Ben Pfaff wrote:
>Fr************@googlemail.com writes:
<snip>
>>Now this can quite easily be corrected by macros, for example:

#include <stdio.h>

#define fputs(X,Y) fputs(Y,X)

I would recommend doing that. For one thing, the implementation
^^^^^ would not
>is allowed to declare a macro from each standard library
function. For another, you'll confuse any C programmer who reads
your code.

Is that *wouldn't*?
Yes, thanks.
--
"I'm not here to convince idiots not to be stupid.
They won't listen anyway."
--Dann Corbit
Mar 9 '07 #8

P: n/a
"Servé Laurijssen" <se*@n.tkwrites:
2. Is it possible for implementations to offer fputs as a macro only or must
it always be a real function too?
There always has to be a function definition. It's perfectly
valid to do
#undef fputs
and then use fputs. Or you can call the function as
(fputs)(...), which doesn't get expanded.
--
int main(void){char p[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv wxyz.\
\n",*q="kl BIcNBFr.NKEzjwCIxNJC";int i=sizeof p/2;char *strchr();int putchar(\
);while(*q){i+=strchr(p,*q++)-p;if(i>=(int)sizeof p)i-=sizeof p-1;putchar(p[i]\
);}return 0;}
Mar 9 '07 #9

P: n/a
Fr************@googlemail.com wrote:
>
I'm finding it really hard to keep some of these things straight...
For example, fputs is to puts as fprintf is to printf, except that
fputs has the file handle at the end and fprintf at the beginning!
Very illogical! And hard to remember.
Think of it this way - the file id goes on the end, if possible.
For a variadic function the end is unknown, so the file id goes at
the beginning. If you follow this rule for your own FILE handling
functions there will be no confusion.

I suspect the original reason has to do with the convenience of
writing the actual functions, combined with the original C practice
of pushing arguments in reverse order. Thus the non-variadic
functions want to do all their manipulations, and only at the end
need to access the deeply buried file id.

Note that these are neither ids nor handles. They are FILE*
pointers to a stream control block of some form or other.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>

--
Posted via a free Usenet account from http://www.teranews.com

Mar 9 '07 #10

P: n/a
To understand the reason for the inconsistencies, you
must realize that the C library did not spring full-armed
from thebrow of Jove.
<snip>

Thanks for the humorous explanation, and to Ben Pfaff for a nice
mnemonic.
But oh, dear Lord, sweet Jesus, don't do this, I beg!
If you simply *must* introduce macros to arrange things to
your liking, at least give them names that don't look like
something else! Your code will be completely unreadable,
and (you will discover) unreadable code tends to acquire
an unusually high density of bugs -- and then turn out to
be unmaintainable. When you write code you will be writing
in a private language nobody else understands -- and you
will also find your own ability to read the common language
diminished. If you cannot live without your silly macro,
at least have the decency to call it `BFTSPLX'.
How about Fputs then?
main() /* note: returning int not void!! */

("But not for long!" -- Sweeney Todd) Under the new
"C99" version of the Standard, it is illegal to omit the
type. Typing "eye enn tee space" saves keystrokes, compared
to the comment you had to type to defend its omission.
Normally I wouldn't put a comment - I think having int as the default
return type really helps streamline code. The comment was because
several people from this group recently expressed to me a strong
preference for main returning int not void, so I wanted to emphasize
that I'm now following their advice.
{
fprintf((FILE *) stdout, "A test\n");

Useless cast, since `stdout' is already a `FILE*'
My stdio.h implements std(in|out|err) as macros, so I thought it best
to be on the safe side and typecast. (In fact there's a funny comment
about that in stdio.h:
/* C89/C99 say they're macros. Make them happy. */
)
So basically I was planning to build up a list of macro definitions to
regulate whatever inconsistencies I come through in stdlib, then I can
put them in a header to be #included in all my programs. But surely
other people will already have done this, so I thought I'd ask if any
such list is available somewhere before reinventing the wheel.

Nobody in his right mind has done such a thing, I am sure.
Invent your wheel if you must; I am sure it will roll you
straight to Perdition.
Hmmm, does it really seem like such an outlandish thing? After all if
another programmer does read my code he'll have easy access to any
macro definitions, so that shouldn't cause too much difficulty.
"A foolish consistency is the hobgoblin of little minds,
Adored by little statesmen and philosophers and divines."
-- Ralph Waldo Emerson

"That leg's long enough; pull on the other."
-- Anonymous

--
Eric.Sos...@sun.com
Mar 9 '07 #11

P: n/a
Eric Sosman <Er*********@sun.comwrites:
Servé Laurijssen wrote On 03/09/07 14:48,:
>"Eric Sosman" <Er*********@sun.comwrote in message
news:1173467521.93207@news1nwk...
>>>>#define fputs(X,Y) fputs(Y,X)

You need to start with `#undef fputs' to guard against
the possibility that <stdio.hhas already defined `fputs'
as a macro.


2 questions pop up.

1. Creating a macro with the same name as an already existing function is
not undefined behaviour?

No. It may look at first like an infinite recursion,
but macros are not expanded recursively. That is, if the
expansion of macro M generates another appearance of M,
directly or indirectly, the generated M is not treated as
a macro.
[...]

I was about to say that fputs is reserved, not because of the infinite
recursion problem, but because it's defined in a standard header. But
fortunately I checked the standard first. C99 7.1.3:

All identifiers with external linkage in any of the following
subclauses (including the future library directions) are always
reserved for use as identifiers with external linkage.

This includes "fputs". Since macros don't have external linkage, you
can legally define a macro "fputs" (if you #undef it first).

But this is one of those cases where an identifier is reserved for
some purposes, but it's easier just to avoid redeclaring or redefining
it altogether. There are some moderately complex rules about which
identifiers are reserved for what; I prefer to pretend that all such
identifiers are reserved for all purposes. For example, I avoid all
identifiers that start with an underscore, even though some of them
are permitted for some uses.

The proposed fputs() macro with the arguments swapped is an example of
why such redefinitions are a bad idea. The compiler may be required
to let you get away with it, but it's still wise to show some mercy to
the next person who reads or maintains your code -- even if that's
only you.

--
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."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Mar 9 '07 #12

P: n/a
I would recommend doing that. For one thing, the implementation
is allowed to declare a macro from each standard library
function.
Wouldn't a modern C preprocessor expand macros recursively?

Mar 9 '07 #13

P: n/a
Fr************@googlemail.com writes:
>I would recommend doing that. For one thing, the implementation
is allowed to declare a macro from each standard library
function.

Wouldn't a modern C preprocessor expand macros recursively?
No.
--
int main(void){char p[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv wxyz.\
\n",*q="kl BIcNBFr.NKEzjwCIxNJC";int i=sizeof p/2;char *strchr();int putchar(\
);while(*q){i+=strchr(p,*q++)-p;if(i>=(int)sizeof p)i-=sizeof p-1;putchar(p[i]\
);}return 0;}
Mar 9 '07 #14

P: n/a
Eric Sosman wrote:
Servé Laurijssen wrote On 03/09/07 14:48,:
"Eric Sosman" <Er*********@sun.comwrote in message
news:1173467521.93207@news1nwk...
>>#define fputs(X,Y) fputs(Y,X)

You need to start with `#undef fputs' to guard against
the possibility that <stdio.hhas already defined `fputs'
as a macro.

2 questions pop up.

1. Creating a macro with the same name as an already existing function is
not undefined behaviour?

No. It may look at first like an infinite recursion,
but macros are not expanded recursively. That is, if the
expansion of macro M generates another appearance of M,
directly or indirectly, the generated M is not treated as
a macro.
That's correct. However, define a macro with the same name as a
standard library function whose header is included, and the behaviour
is undefined. Even if you undefine any pre-existing macro first, and
even if the compiler would need special magic to have any problem with
your custom definition.

Mar 9 '07 #15

P: n/a
Fr************@googlemail.com wrote On 03/09/07 17:28,:
[... large snip; in re using macros to permute the arguments
of standard functions, e.g. #define fputs(x,y) fputs(y,x) ...]
Hmmm, does it really seem like such an outlandish thing? After all if
another programmer does read my code he'll have easy access to any
macro definitions, so that shouldn't cause too much difficulty.
Try an experiment. Construct a sign that reads

<--- RIGHT

LEFT --->

and attach it to the rear of your car where everyone can
see it easily so there'll be no confusion. Also, find the
wiring harness and exchange the cables that lead to your
car's directional signals, so they'll be consistent with
your new nomenclature. Let us know how things work out.

(This procedure would make you a perfectly normal
Boston driver, if it weren't for the sign ...)

--
Er*********@sun.com
Mar 9 '07 #16

P: n/a
Keith Thompson wrote:
Eric Sosman <Er*********@sun.comwrites:
Servé Laurijssen wrote On 03/09/07 14:48,:
"Eric Sosman" <Er*********@sun.comwrote in message
news:1173467521.93207@news1nwk...

#define fputs(X,Y) fputs(Y,X)

You need to start with `#undef fputs' to guard against
the possibility that <stdio.hhas already defined `fputs'
as a macro.
2 questions pop up.

1. Creating a macro with the same name as an already existing functionis
not undefined behaviour?
No. It may look at first like an infinite recursion,
but macros are not expanded recursively. That is, if the
expansion of macro M generates another appearance of M,
directly or indirectly, the generated M is not treated as
a macro.
[...]

I was about to say that fputs is reserved, not because of the infinite
recursion problem, but because it's defined in a standard header. But
fortunately I checked the standard first. C99 7.1.3:

All identifiers with external linkage in any of the following
subclauses (including the future library directions) are always
reserved for use as identifiers with external linkage.

This includes "fputs". Since macros don't have external linkage, you
can legally define a macro "fputs" (if you #undef it first).
7.1.3 says more than just that:

p1:
Each identifier with file scope listed in any of the following
subclauses (including the future library directions) is reserved for
use as a macro name and as an identifier with file scope in the same
name space if any of its associated headers is included.

p2:
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.

So fputs is reserved for use as a macro name (regardless of whether
you undefined it), and even if it wasn't, you still wouldn't be
allowed to define it as a macro yourself.

Mar 9 '07 #17

P: n/a
Fr************@googlemail.com writes:
> To understand the reason for the inconsistencies, you
must realize that the C library did not spring full-armed
from thebrow of Jove.
<snip>
*Please* don't snip attribution lines (lines of the form
"So-and-so <fo*@bar.comwrites:"). Knowing who wrote what makes the
discussion easier to follow, and giving proper credit is just polite.

[...]
How about Fputs then?
If you must do it, I suppose Fputs is a decent name. Some very old
linkers don't necessarily distinguish between upper and lower case for
external names, but I don't *think* that's likely to be a problem in
practice.

But I'm hesitant to offer too much advice on what to call these
things, since I think they're a bad idea in the first place. The
rules really aren't all that complex. You'll likely spend less time
learning them than you'd spend implementing your aliases -- and as a
result, you'll be better able to read other people's code (because
others aren't going to use your aliases), and other people will be
better able to read your code.
main() /* note: returning int not void!! */

("But not for long!" -- Sweeney Todd) Under the new
"C99" version of the Standard, it is illegal to omit the
type. Typing "eye enn tee space" saves keystrokes, compared
to the comment you had to type to defend its omission.

Normally I wouldn't put a comment - I think having int as the default
return type really helps streamline code. The comment was because
several people from this group recently expressed to me a strong
preference for main returning int not void, so I wanted to emphasize
that I'm now following their advice.
Bravo. But the point is that you only followed *part* of their
advice. Leaving out the word "int" is allowed (in C90, but not in
C99), but you gain nothing by doing so. Leaving out the word "void"
is also allowed, but again, you gain nothing by doing so. Change it
from "main()" to "int main(void)", and get into the habit of writing
it that way. Trust me on this; you'll be happier in the long run.
{
fprintf((FILE *) stdout, "A test\n");

Useless cast, since `stdout' is already a `FILE*'

My stdio.h implements std(in|out|err) as macros, so I thought it best
to be on the safe side and typecast. (In fact there's a funny comment
about that in stdio.h:
/* C89/C99 say they're macros. Make them happy. */
)
Yes, the standard requires stdin, stdout, and stderr to be macros. It
also requires those macros to expand to expressions of type FILE*.
There is no realistic chance that an implementation will get this
wrong. If one did, it's not likely that casting ("typecast" isn't a
word unless you're talking about actors) will do any good.

[...]
Hmmm, does it really seem like such an outlandish thing? After all if
another programmer does read my code he'll have easy access to any
macro definitions, so that shouldn't cause too much difficulty.
Yes, it really does seem like such an outlandish thing. How is
someone reading your code going to know where your macro definitions
are? Presumably they'd be in some header you've written, but where is
it? Did you put it in the same directory as the source file that uses
it, or is it in a separate "include" directory, or is it off somewhere
else altogether?

And if I have to track down your macro definition to figure out what
Fputs(foo, bar) means, that tells me that it really means
fputs(bar, foo) -- but I *still* have to know that fputs() expects a
char* followed by a FILE*.

I can certainly understand the temptation to try to turn C into
something just a little bit better. The original Bourne shell under
Unix was originally written using a set of macros that made the
source look Pascalish:

#define BEGIN {
#define END }
#define IF if (
#define THEN )
#define ELSE } else {

The result was nearly illegible both to C programmers and to Pascal
programmers.

I like some languages better than others, but I generally try to
accept each language on its own terms.

In the 8th of Henry Spencer's "The Ten Commandments for C
Programmers", he wrote that "thy creativity is better used in solving
problems than in creating beautiful new impediments to understanding".

--
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."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Mar 10 '07 #18

P: n/a
"Keith Thompson" <ks***@mib.orgwrote in message
news:ln************@nuthaus.mib.org...
Another common way to avoid the confusion is to use just,
say, printf() and fprintf() rather than fputs:

fprintf(stderr, "Another test\n");
fprintf(stderr, "%s\n", message);

This has some cost in performance, but that's usually not significant.
A decent compiler will replace fprintf() calls with fputs() calls when it
can do so safely (ditto for printf() and puts()), such as in the cases
above. There's no reason to use fputs() at all these days. Let the
compiler do the work for you, and don't mess with tiny, premature
optimization steps unless you can prove it's not doing a good enough job.

S

--
Stephen Sprunk "Those people who think they know everything
CCIE #3723 are a great annoyance to those of us who do."
K5SSS --Isaac Asimov
--
Posted via a free Usenet account from http://www.teranews.com

Mar 10 '07 #19

P: n/a
Ben Pfaff wrote:
Fr************@googlemail.com writes:
.... snip ...
>>
#define fputs(X,Y) fputs(Y,X)

I would recommend doing that. For one thing, the implementation
^^^
is allowed to declare a macro from each standard library
function. For another, you'll confuse any C programmer who reads
your code.
I suspect an elided 'not'.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>

--
Posted via a free Usenet account from http://www.teranews.com

Mar 10 '07 #20

P: n/a
Eric Sosman wrote:
Fr************@googlemail.com wrote On 03/09/07 13:24,:
.... snip ...
>>
So basically I was planning to build up a list of macro definitions
to regulate whatever inconsistencies I come through in stdlib, then
I can put them in a header to be #included in all my programs. But
surely other people will already have done this, so I thought I'd
ask if any such list is available somewhere before reinventing the
wheel.

Nobody in his right mind has done such a thing, I am sure. Invent
your wheel if you must; I am sure it will roll you straight to
Perdition.

"A foolish consistency is the hobgoblin of little minds,
Adored by little statesmen and philosophers and divines."
-- Ralph Waldo Emerson

"That leg's long enough; pull on the other."
-- Anonymous
See sig.

--
"I am enclosing two tickets to the first night of my new play.
Bring a friend, if you have one." -- George Bernard Shaw.
"Cannot possibly attend first night; will attend second, if
there is one" -- Winston Churchill, in reply.

--
Posted via a free Usenet account from http://www.teranews.com

Mar 10 '07 #21

P: n/a
"Harald van Dijk" <tr*****@gmail.comwrites:
Eric Sosman wrote:
>Servé Laurijssen wrote On 03/09/07 14:48,:
"Eric Sosman" <Er*********@sun.comwrote in message
news:1173467521.93207@news1nwk...

#define fputs(X,Y) fputs(Y,X)

You need to start with `#undef fputs' to guard against
the possibility that <stdio.hhas already defined `fputs'
as a macro.
2 questions pop up.

1. Creating a macro with the same name as an already existing function is
not undefined behaviour?

No. It may look at first like an infinite recursion,
but macros are not expanded recursively. That is, if the
expansion of macro M generates another appearance of M,
directly or indirectly, the generated M is not treated as
a macro.

That's correct. However, define a macro with the same name as a
standard library function whose header is included, and the behaviour
is undefined. Even if you undefine any pre-existing macro first, and
even if the compiler would need special magic to have any problem with
your custom definition.
I don't *think* that's correct. See the rules for reserved
identifiers in 7.1.3; I think fputs, for example, is reserved only for
use as an identifier with external linkage.

But re-using the name "fputs" is A Bad Idea, regardless of whether
it's strictly allowed. The only good excuse I can think of for doing
so would be to work around a buggy implementation. (Using the
parameter order specified by the standard is not something I consider
to be a bug.)

--
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."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Mar 10 '07 #22

P: n/a
"Harald van Dijk" <tr*****@gmail.comwrites:
Keith Thompson wrote:
[...]
>This includes "fputs". Since macros don't have external linkage, you
can legally define a macro "fputs" (if you #undef it first).

7.1.3 says more than just that:

p1:
Each identifier with file scope listed in any of the following
subclauses (including the future library directions) is reserved for
use as a macro name and as an identifier with file scope in the same
name space if any of its associated headers is included.

p2:
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.

So fputs is reserved for use as a macro name (regardless of whether
you undefined it), and even if it wasn't, you still wouldn't be
allowed to define it as a macro yourself.
Ok, you're right. (I was incorrectly thinking of "external linkage"
and "file scope" as exclusive properties; clearly they aren't.)

--
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."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Mar 10 '07 #23

P: n/a
Keith Thompson <ks***@mib.orgwrites:
Fr************@googlemail.com writes:
[...]
>Hmmm, does it really seem like such an outlandish thing? After all if
another programmer does read my code he'll have easy access to any
macro definitions, so that shouldn't cause too much difficulty.

Yes, it really does seem like such an outlandish thing.
[snip]

Incidentally, if you're feeling attacked, please don't. It might seem
like everyone is piling on to tell you repeatedly that you're wrong,
Wrong, WRONG!!, but it's nothing personal. The idea you're presenting
is actually a fairly interesting one, and I've learned a thing or two
in the course of discussing it. (I'm not changing my position, just
clarifying the context of the discussion.)

--
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."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Mar 10 '07 #24

P: n/a
Keith Thompson <ks***@mib.orgwrites:
"Harald van Dijk" <tr*****@gmail.comwrites:
[...]
>That's correct. However, define a macro with the same name as a
standard library function whose header is included, and the behaviour
is undefined. Even if you undefine any pre-existing macro first, and
even if the compiler would need special magic to have any problem with
your custom definition.

I don't *think* that's correct. See the rules for reserved
identifiers in 7.1.3; I think fputs, for example, is reserved only for
use as an identifier with external linkage.
Harald was right; I was wrong.

--
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."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Mar 10 '07 #25

P: n/a
Keith Thompson wrote:
Keith Thompson <ks***@mib.orgwrites:
>Fr************@googlemail.com writes:
[...]
>>Hmmm, does it really seem like such an outlandish thing? After all if
another programmer does read my code he'll have easy access to any
macro definitions, so that shouldn't cause too much difficulty.
Yes, it really does seem like such an outlandish thing.
[snip]

Incidentally, if you're feeling attacked, please don't. It might seem
like everyone is piling on to tell you repeatedly that you're wrong,
Wrong, WRONG!!, but it's nothing personal. The idea you're presenting
is actually a fairly interesting one, and I've learned a thing or two
in the course of discussing it. (I'm not changing my position, just
clarifying the context of the discussion.)
And (as one who might be viewed as an attacker), I confess
similar urges in my younger days. For a mercifully brief while,
I had near the top of many of my source files

#define until(x) while(!(x))

(Maybe you can imagine why.) It didn't take an absurdly long
time for this impulse to fade; perhaps yours, too, will be
similarly and mercifully short-lived.

No one believes C is the perfect language, and as Young
Turks we all go through a phase of believing we can improve on
it. With time comes the wisdom to understand (and accept) that
the blemishes have their own beauty, and that that some of the
wisdom built into C would not survive "improvement."

--
Eric Sosman
es*****@acm-dot-org.invalid
Mar 10 '07 #26

P: n/a
Eric Sosman <es*****@acm-dot-org.invalidwrites:
Keith Thompson wrote:
>Keith Thompson <ks***@mib.orgwrites:
>>Fr************@googlemail.com writes:
[...]
>>>Hmmm, does it really seem like such an outlandish thing? After all if
another programmer does read my code he'll have easy access to any
macro definitions, so that shouldn't cause too much difficulty.
Yes, it really does seem like such an outlandish thing.
[snip]
Incidentally, if you're feeling attacked, please don't. It might
seem
like everyone is piling on to tell you repeatedly that you're wrong,
Wrong, WRONG!!, but it's nothing personal. The idea you're presenting
is actually a fairly interesting one, and I've learned a thing or two
in the course of discussing it. (I'm not changing my position, just
clarifying the context of the discussion.)

And (as one who might be viewed as an attacker), I confess
similar urges in my younger days. For a mercifully brief while,
I had near the top of many of my source files

#define until(x) while(!(x))

(Maybe you can imagine why.) It didn't take an absurdly long
time for this impulse to fade; perhaps yours, too, will be
similarly and mercifully short-lived.

No one believes C is the perfect language, and as Young
Turks we all go through a phase of believing we can improve on
it. With time comes the wisdom to understand (and accept) that
the blemishes have their own beauty, and that that some of the
wisdom built into C would not survive "improvement."
And then there are a few people, like Bjarne Stroustrup (inventor of
C++), Brad Cox and Tom Love (the inventors of Objective C), and a few
others, who actually go on to invent new languages that are intended
to be better versions of C. Doing this right takes a *lot* of work.
Rule One: You can't change just one thing. (Whether Stroustrup and
company are brilliant language designers or just Young Turks who
didn't know when to quit is another question, one that I urge everyone
here to leave unanswered.)

--
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."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Mar 10 '07 #27

P: n/a

"Keith Thompson" <ks***@mib.orgwrote in message
news:ln************@nuthaus.mib.org...
And then there are a few people, like Bjarne Stroustrup (inventor of
C++), Brad Cox and Tom Love (the inventors of Objective C), and a few
others, who actually go on to invent new languages that are intended
to be better versions of C. Doing this right takes a *lot* of work.
Rule One: You can't change just one thing. (Whether Stroustrup and
company are brilliant language designers or just Young Turks who
didn't know when to quit is another question, one that I urge everyone
here to leave unanswered.)
In his book "The design and evolution of C++" you will learn that C++ never
started out to "improve on C". It started out as a low level language with
classes added as in Simula. Just that at some point a decision had to be
made on the syntax and C seemed the best choice at that time. You're
presenting it here as if the problem solved by C++ was that "C is crappy"
but that wasnt the case at all. The problem solved was "we dont have a low
level language with which you can design programs as how you think of them
as in the real world" (classes)
Mar 10 '07 #28

P: n/a
"Servé Laurijssen" <se*@n.tkwrites:
"Keith Thompson" <ks***@mib.orgwrote in message
news:ln************@nuthaus.mib.org...
>And then there are a few people, like Bjarne Stroustrup (inventor of
C++), Brad Cox and Tom Love (the inventors of Objective C), and a few
others, who actually go on to invent new languages that are intended
to be better versions of C. Doing this right takes a *lot* of work.
Rule One: You can't change just one thing. (Whether Stroustrup and
company are brilliant language designers or just Young Turks who
didn't know when to quit is another question, one that I urge everyone
here to leave unanswered.)

In his book "The design and evolution of C++" you will learn that C++ never
started out to "improve on C". It started out as a low level language with
classes added as in Simula. Just that at some point a decision had to be
made on the syntax and C seemed the best choice at that time. You're
presenting it here as if the problem solved by C++ was that "C is crappy"
but that wasnt the case at all. The problem solved was "we dont have a low
level language with which you can design programs as how you think of them
as in the real world" (classes)
I'll have to take your word for that; it's been a long time since I
read that book. It's off-topic, so I won't get into it any further.

--
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."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Mar 10 '07 #29

P: n/a
Fr************@googlemail.com wrote:
# I'm finding it really hard to keep some of these things straight...
# For example, fputs is to puts as fprintf is to printf, except that
# fputs has the file handle at the end and fprintf at the beginning!
# Very illogical! And hard to remember.

Yeah, sucks sometimes.

# Now this can quite easily be corrected by macros, for example:
#
# #include <stdio.h>
#
# #define fputs(X,Y) fputs(Y,X)

This will fail if fputs is a function. What you need to do
in this case is
#define fputs(X,Y) (fputs)(Y,X)
This will also fail if fputs is a #define.

Overall it's safer to come up with your own names so there's
no danger of conflict.
#define wts(X,Y) (fputs(Y,X))
#define wtc(X,Y) (fputc(Y,X))
...

If your compiler supports inline, it's even better to use that
inline int wts(FILE *f,char *s) {
return fputs(s,f);
}
since you get typechecking and you can define variables and
use iterations inside your function.

--
SM Ryan http://www.rawbw.com/~wyrmwif/
I ASSURE YOU WE'RE OPEN!
Mar 10 '07 #30

P: n/a
On Mar 10, 12:50 am, Keith Thompson <k...@mib.orgwrote:
Incidentally, if you're feeling attacked, please don't. It might seem
like everyone is piling on to tell you repeatedly that you're wrong,
Wrong, WRONG!!, but it's nothing personal. The idea you're presenting
is actually a fairly interesting one, and I've learned a thing or two
in the course of discussing it. (I'm not changing my position, just
clarifying the context of the discussion.)
No, not at all. I'm very grateful for the advice people have given me.
In this thread, several people have argued very persuasively that my
idea for reordering arguments is a flawed one, and I'm now convinced
that the right thing to do is stick to the standard order, consulting
man pages as necessary.

--
Keith Thompson (The_Other_Keith) k...@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."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Mar 10 '07 #31

P: n/a
On Mar 10, 11:50 am, Eric Sosman <Eric.Sos...@sun.comwrote:
>
Try an experiment. Construct a sign that reads

<--- RIGHT

LEFT --->
Might not be as bad as you think. My work recently moved into a new
office and we have a sign laid out just like that, except RIGHT was
our name and LEFT was another company in the same building. However,
we kept getting arrivals for the other company! Eventually someone
figured out that the arrivals were associating the written name with
the arrow above/below it, rather than the one beside it. We moved our
sign up and to the side, and have had far fewer misdirected arrivals
since.

Mar 11 '07 #32

P: n/a
On Mar 10, 11:28 am, Francine.Ne...@googlemail.com wrote:
{
fprintf((FILE *) stdout, "A test\n");
Useless cast, since `stdout' is already a `FILE*'

My stdio.h implements std(in|out|err) as macros, so I thought it best
to be on the safe side and typecast.
How is that safe? If you think it is safe then you must have some
misconceptions about C (so it would be good to sort them out now
rather than later).

If anything, it is unsafe, e.g. if you had a variable elsewhere:
int stout;

and accidentally made a typo:
fprintf((FILE *) stout, "A test\n");

then you may not get a compiler warning, where you would have got one
without the cast.

Mar 11 '07 #33

P: n/a
Fr************@googlemail.com writes:
>
[regarding redefinition of fputs() to fputs(FILE *, const char *)]

Hmmm, does it really seem like such an outlandish thing? After all if
another programmer does read my code he'll have easy access to any
macro definitions, so that shouldn't cause too much difficulty.
Yes, it does seem such an outlandish thing. It only serves your current
purpose. Later down, you will have to be *extremely* careful about the
header which includes this redefinition of fputs(). If some unlucky
soul happens to include your magic header in a C source file which
abides by the standard order of fputs() arguments, all sorts of
``interesting'' bugs will start manifesting their extremely funny idea
of how your program should crash.

Mar 27 '07 #34

P: n/a
Giorgos Keramidas wrote:
Fr************@googlemail.com writes:
>[regarding redefinition of fputs() to fputs(FILE *, const char *)]

Hmmm, does it really seem like such an outlandish thing? After all if
another programmer does read my code he'll have easy access to any
macro definitions, so that shouldn't cause too much difficulty.

Yes, it does seem such an outlandish thing. It only serves your current
purpose. Later down, you will have to be *extremely* careful about the
header which includes this redefinition of fputs(). If some unlucky
soul happens to include your magic header in a C source file which
abides by the standard order of fputs() arguments, all sorts of
``interesting'' bugs will start manifesting their extremely funny idea
of how your program should crash.
s/crash/fail to compile/

Still, it remains an outlandish thing.

--
Eric Sosman
es*****@acm-dot-org.invalid
Mar 27 '07 #35

P: n/a
On Mar 27, 7:56 am, Eric Sosman <esos...@acm-dot-org.invalidwrote:
Giorgos Keramidas wrote:
Francine.Ne...@googlemail.com writes:
[regarding redefinition of fputs() to fputs(FILE *, const char *)]
Hmmm, does it really seem like such an outlandish thing? After all if
another programmer does read my code he'll have easy access to any
macro definitions, so that shouldn't cause too much difficulty.
Yes, it does seem such an outlandish thing. It only serves your current
purpose. Later down, you will have to be *extremely* careful about the
header which includes this redefinition of fputs(). If some unlucky
soul happens to include your magic header in a C source file which
abides by the standard order of fputs() arguments, all sorts of
``interesting'' bugs will start manifesting their extremely funny idea
of how your program should crash.

s/crash/fail to compile/
Unless the arguments are passed as void pointers, contrived but
possible.

Robert Gamble
Mar 27 '07 #36

This discussion thread is closed

Replies have been disabled for this discussion.