Do we need to continue to include stdio.h in C files ?

  • Thread starter karthikbalaguru
  • Start date
R

Richard Bos

Eric Sosman said:
Keep in mind that the Standard library undergoes change, and
sometimes grows new identifiers it didn't possess before. As a
specific example, what do you think would happen if the contents
of <stdbool.h> were foisted willy-nilly upon every compilation,
even of source that was written before <stdbool.h> came along?

The same thing that happened to my own code, which makes frequent use of
the identifiers outfile and infile for FILE *s, and for line buffers,
outline and... yes, inline. *Kaboom*. Except that what happened was
_nothing at all_: that code is still just as valid C89 code as it was
before. Ok, if I want to make use of the new features of C99, I'll have
to change all that code to use different identifiers; but since those
programs got along quite well without, why should I bother?
I still have compilers for the previous Standard ready to use; the
existence, beside these, of compilers for the new Standard, which accept
more predefined identifiers, and fewer user-defined ones, is no problem
at all.
Name collisions are a continuing problem for C, a problem that
would be made worse and not better if code became entirely unable
to avoid bumping into the library's names.

It already is.

Richard
 
S

Stephen Sprunk

Richard said:
That, too, would be very useful for third-party libraries, but not for
the Standard functions. There is no way that printf() or isalnum() can
ever cause a namespace clash in a wisely-written program, so there is no
need to have them in separate namespaces.

I disagree with the language treating standard library functions as
"special"; they're just functions that ANSI/ISO chose to guarantee will
be available (in most cases), nothing more. Put them in a "std" name
space just like C++ does; that provides you a name space to refer to for
clarity if there is a conflict (e.g. to distinguish a std::string from a
foo::string when "string" could mean either due to multiple "using"
statements).

More importantly, new functions could be added to the standard library
in the future, and name spaces would keep them from conflicting with
user-defined functions or variables that were previously available.
That leaves only new keywords as potential problems, which is quite an
improvement.
Things are different for tr_add (which adds an element, from the tree
library) and tr_add (from the address management library, which
translates one to another format). Since no library writer knows all
other libraries out there, clashes between them are inevitable

Many library authors already use name spaces of a sort: the name of the
library is prepended to all function names in the API (e.g. tree_add()
is the "add" function from the "tree" library -- the other tr_add() you
mention would be addr_tr(), so no collision). All collisions I've
experienced came from libraries that didn't follow this convention; it's
obviously possible for two authors to choose the same name and collide
that way, but what are the odds that two unrelated libraries that you'd
want to use happen to have the same name?
But everybody knows the Standard library.

You haven't been paying attention here, then; it's quite clear that a
lot of programmers do _not_ know the C Standard Library.

S
 
D

Dik T. Winter

> On Wed, 11 Mar 2009 02:51:06 GMT, "Dik T. Winter"

>
> Perhaps you could clarify this issue a bit. How is the "with"
> any worse than including files. In either case there is a
> construct that brings in an entire suite of definitions that are
> not visible in the code.

Indeed, include files can also be abused in such a way that the definitions
in the include file hide other definitions. But with the "with" statement
it is a bit more likely.
 
R

Richard Bos

Stephen Sprunk said:
I disagree with the language treating standard library functions as
"special"; they're just functions that ANSI/ISO chose to guarantee will
be available (in most cases), nothing more.

But that _is_ special, because it means that every (hosted)
implementation must provide them, and therefore that every C programmer
must know about them. In this, they are completely different from
functions from any third-party library.
Put them in a "std" name space just like C++ does; that provides you a
name space to refer to for clarity if there is a conflict (e.g. to
distinguish a std::string from a foo::string when "string" could mean
either due to multiple "using" statements).

This requires the innocent programmer to jump through hoops, only
because some library writer wasn't paying attention.

I have no problem if you want to suggest that foo::strcpy needs to be in
a name space. But the Standard strcpy() should not need to be.
More importantly, new functions could be added to the standard library
in the future, and name spaces would keep them from conflicting with
user-defined functions or variables that were previously available.
That leaves only new keywords as potential problems, which is quite an
improvement.

You guys keep talking as if the Committee adds functions left, right and
centre, all the time, and there's no way for us poor programmers to keep
our code clean. Well, they don't. Every ten years or so (if that) they
bring out a new Standard. _And_ the old ones continue to be around, and
compilers continue to compile to the old Standards as well as the new
one.
You haven't been paying attention here, then; it's quite clear that a
lot of programmers do _not_ know the C Standard Library.

Grmbl. I considered adding "(should)" to that sentence, but couldn't
bear the broken grammar. I should have.

Richard
 
S

Stephen Sprunk

Richard said:
But that _is_ special, because it means that every (hosted)
implementation must provide them, and therefore that every C programmer
must know about them.

"Must"? No. There are plenty of Standard Library functions I know
nothing about; I see new (to me) ones mentioned here regularly. It is
hardly mandatory that _every_ programmer must know them; they may
accidentally invoke UB if they don't, but you can write C programs just
fine without using (or even knowing) _any_ of the Standard Library.
I've written a lot of POSIX-specific code that _never_ uses the Standard
Library or includes any of the Standard headers, and a lot more that
doesn't use any Standard functions except snprintf().
In this, they are completely different from functions from any third-
party library.

I can see your point, though I disagree with it. The Standard Library
is required to be there (on hosted systems), and it's implementation is
almost always linked in by default, but otherwise it is no different
from any other library, and I see no point in treating it as "special"
when it's easier _not_ to do so.

While not directly relevant, the designers of C++, Java, C#, etc. put
their standard libraries in separate name spaces; I don't know exactly
why, but I'd be hesitant to ignore their example without a very
compelling reason, which you have yet to provide...
This requires the innocent programmer to jump through hoops, only
because some library writer wasn't paying attention.

I have no problem if you want to suggest that foo::strcpy needs to be in
a name space. But the Standard strcpy() should not need to be.

Ah, but when foo::strcpy() is the one you get when you type just
strcpy(), how are you going to specify the Standard strcpy()?

I understand why you think that's a bad situation to put yourself in,
and I avoid it (or any other name space conflicts) when at all possible,
but a solution is still needed at times through no fault of the
programmer who's stuck with the problem, and C++'s solution is
reasonable and easy.
You guys keep talking as if the Committee adds functions left, right and
centre, all the time, and there's no way for us poor programmers to keep
our code clean. Well, they don't. Every ten years or so (if that) they
bring out a new Standard. _And_ the old ones continue to be around, and
compilers continue to compile to the old Standards as well as the new
one.

One of the reasons that ISO is so reluctant to add new functions is that
they don't want to break existing code...

It's not the most serious problem, I'll grant, but it's one that can't
be ignored entirely, particularly when there's an easy solution to it.

There's no solution at all to the problems with adding new keywords,
which is one of the reasons that "static" means so many darn different
things when there really should be different keywords for each use...
Grmbl. I considered adding "(should)" to that sentence, but couldn't
bear the broken grammar. I should have.

:)

S
 
K

Keith Thompson

Stephen Sprunk said:
One of the reasons that ISO is so reluctant to add new functions is
that they don't want to break existing code...

It's not the most serious problem, I'll grant, but it's one that can't
be ignored entirely, particularly when there's an easy solution to it.

There's no solution at all to the problems with adding new keywords,
which is one of the reasons that "static" means so many darn different
things when there really should be different keywords for each use...

In fact, there is a solution, one used (partially) in the C99
standard. New keywords can be defined using reserved identifiers.
See _Bool, _Complex, and _Imaginary. (On the other hand, see inline
and restrict, which did have the potential of breaking existing code.)
 
J

jacob navia

Keith said:
In fact, there is a solution, one used (partially) in the C99
standard. New keywords can be defined using reserved identifiers.
See _Bool, _Complex, and _Imaginary. (On the other hand, see inline
and restrict, which did have the potential of breaking existing code.)

And yet another solution is the one proposed by lcc-win.

CONTEXTUAL keywords.

For instance in lcc-win you can write

int overloaded fn(int,double);

meaning that this is an overloaded function.

But you can STILL write

int overloaded = 42;

The "overloaded" marker is a marker only in the context of a
function definition. Elsewhere the "keyword" has no special meaning.

This solution allows to introduce a marker without breaking existing
code.


This is a better solution that the underscore (horrible) and the
new keyword.
 
K

Keith Thompson

jacob navia said:
And yet another solution is the one proposed by lcc-win.

CONTEXTUAL keywords.

For instance in lcc-win you can write

int overloaded fn(int,double);

meaning that this is an overloaded function.

But you can STILL write

int overloaded = 42;

The "overloaded" marker is a marker only in the context of a
function definition. Elsewhere the "keyword" has no special meaning.

This solution allows to introduce a marker without breaking existing
code.


This is a better solution that the underscore (horrible) and the
new keyword.

An interesting idea, but I do see some potential drawbacks.

Depending on how a new contextual keyword is to be used, I can imagine
that it might introduce some ambiguities. It's quite possible that,
in this particular case, it doesn't, but off the top of my head I
can't prove that it doesn't -- and that worries me.

The nice thing about keywords that are reserved in all contexts is
that it's easy to tell whether they're being used as keywords or as
identifiers -- they're always keywords. But if I see "overloaded"
somewhere, I have to stop and think about whether it's a keyword in
this context, or just an ordinary identifier.

And if "overloaded" were a marker for a language feature, then using
it as an identifier would, in my opinion, be bad style anyway.

Still, as I said, it's an interesting idea. I tend to prefer purely
reserved keywords, but you need to do something if you're going to add
new ones as the language develops.

<OT>
If I were designing a new language, with no concern for backward
compatibility, I might use case to distinguish between keywords and
other identifiers; for example, keywords might start with an uppercase
letter and identifiers might start with a lowercase letter. I've
worked in a language, Ada, where keywords and identifiers are
case-insensitive, and most coding conventions use case to distinguish
them; I like the idea of making it a language feature rather than a
coding convention. Of course, this couldn't be done for C without
breaking every existing program.
</OT>
 
I

Ike Naar

For instance in lcc-win you can write

int overloaded fn(int,double);

meaning that this is an overloaded function.

But you can STILL write

int overloaded = 42;

So ``overloaded'' is a valid identifier for an int.
Is it also a valid identifier for a function, e.g. can one declare:

int overloaded(int);

(meaning, ``overloaded'' is an ordinary (non-overloaded) function
taking an int argument, returning int)?
 
K

Keith Thompson

So ``overloaded'' is a valid identifier for an int.
Is it also a valid identifier for a function, e.g. can one declare:

int overloaded(int);

(meaning, ``overloaded'' is an ordinary (non-overloaded) function
taking an int argument, returning int)?

Or is "int overloaded(int)" a type name, "overloaded function taking
an int argument and returning int"?
 
B

Ben Bacarisse

jacob navia said:
And yet another solution is the one proposed by lcc-win.

CONTEXTUAL keywords.

For instance in lcc-win you can write

int overloaded fn(int,double);

meaning that this is an overloaded function.

But you can STILL write

int overloaded = 42;

The "overloaded" marker is a marker only in the context of a
function definition. Elsewhere the "keyword" has no special meaning.

It is not clear to me how easy (or hard) it is to make this formal.
For example, do you have a grammar for the language lcc-win accepts?
What sort of grammar is it? Is the following a valid translation unit
for lcc-win?

typedef int overloaded;

overloaded f(overloaded, double);
overloaded overloaded g(overloaded, double);

(I'd expect f to be a plain function and g to be overloaded, but that
is just a guess.)
 
R

Richard Bos

Stephen Sprunk said:
"Must"? No. There are plenty of Standard Library functions I know
nothing about; I see new (to me) ones mentioned here regularly.

*Shrug* There are also many, many drivers who don't know all traffic
laws, but that doesn't mean that every garage exit should have give-way
signs installed.
I can see your point, though I disagree with it. The Standard Library
is required to be there (on hosted systems), and it's implementation is
almost always linked in by default, but otherwise it is no different
from any other library, and I see no point in treating it as "special"
when it's easier _not_ to do so.

That, to me, seems sufficient reason why it _is_ special. Besides, it
may be easier to the compiler writer to treat it as no more special than
any other of his extension libraries, but that was an argument that held
sway in the 1970s. It is now almost the 2010s, and we should rather look
at what is easier for the average programmer. IMO, the average
programmer, today, should not have to remember in which header a
Standard function is declared - he should be able to assume that the
entire Standard library, at least, is available to him at all times.
Ah, but when foo::strcpy() is the one you get when you type just
strcpy(), how are you going to specify the Standard strcpy()?

IMO, if strcpy() gets you foo::strcpy() instead of strcpy(), something
is broken. Plain strcpy() should always get you the Standard one,
exactly because it is Standard.

Richard
 
R

Richard Bos

jacob navia said:
And yet another solution is the one proposed by lcc-win.

CONTEXTUAL keywords.

*Brrrr*

You do keep coming up with ways to make programming unnecessarily
complicated. Where _do_ you get them?

Richard
 
R

Richard Bos

Keith Thompson said:
<OT>
If I were designing a new language, with no concern for backward
compatibility, I might use case to distinguish between keywords and
other identifiers; for example, keywords might start with an uppercase
letter and identifiers might start with a lowercase letter.

You mean Prolog, except that you got them t'otherwayround. A variable
starts with a capital letter or underscore; an atom with a lower case
letter.

Richard
 
K

Keith Thompson

You mean Prolog, except that you got them t'otherwayround. A variable
starts with a capital letter or underscore; an atom with a lower case
letter.

Ok, I'll take your word for it that you're describing Prolog
accurately, but it's not what I had in mind. Perhaps I should look
into it, though.
 
R

Richard Bos

Keith Thompson said:
Ok, I'll take your word for it that you're describing Prolog
accurately, but it's not what I had in mind.

I'm describing at least one version of Prolog accurately (albeit
incompletely, since :- is also an atom, e.g.), but I've never seen a
real standard for the language and implementations differed rather. So
it's quite possible that other implementations did it as you describe
it, and yet others found other solutions.

You do have me wondering which language _you_ were thinking of, though.

Richard
 
K

Keith Thompson

I'm describing at least one version of Prolog accurately (albeit
incompletely, since :- is also an atom, e.g.), but I've never seen a
real standard for the language and implementations differed rather. So
it's quite possible that other implementations did it as you describe
it, and yet others found other solutions.

You do have me wondering which language _you_ were thinking of, though.

No existing one. I really was thinking of a hypothetical new
language, designed from scratch. (Not that I have any intention of
designing a new language.) I was partly inspired by Ada; Ada
identifiers and keywords are case-insensitive, but most common coding
conventions use case to distinguish between them visually.

Don't read too much into my vague musings.
 
J

John F. Eldredge

Speed and memory usage come to mind. On slow machines with little
memory you wanted most modules to compile with as few headers as
possible. With some programs you had to move stuff around between
modules just to get it through the compiler.

Also, the compiler usually has limits on how many different symbols it
can handle. I have seen cases where a large, complex module ended up
having to be split into multiple modules because the number of symbols
became more than the compiler could handle at one time. Each additional
header adds more symbols for the compiler to track, even if you end up
using only one or two symbols from a particular header file.
 

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,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top