Hello
I have been looking at some code which "for faster compilation" has ad hoc
declarations of some standard functions instead of including standard
headers.
E.g.
typedef unsigned int long size_t;
extern void* malloc(size_t);
This feels to me like it's bad style, but I can't quite put my finger on
anything specific that's wrong with it.
What do people think about this approach?
- Ed
|
|
0
|
|
|
|
Reply
|
Edward
|
2/18/2011 9:20:23 PM |
|
On 02/19/11 10:20 AM, Edward Rutherford wrote:
> Hello
>
> I have been looking at some code which "for faster compilation" has ad hoc
> declarations of some standard functions instead of including standard
> headers.
>
> E.g.
>
> typedef unsigned int long size_t;
> extern void* malloc(size_t);
>
> This feels to me like it's bad style, but I can't quite put my finger on
> anything specific that's wrong with it.
>
> What do people think about this approach?
It's terrible style and renders the code non-conforming.
It is not uncommon for system headers to use different types or even
calling conventions for different environments (32/64 bit for example).
Once you start adding your own declarations, you may well end up with
code that at best won't link, at worst links but does weird things. A
quick look at you systems headers should show you what I mean
--
Ian Collins
|
|
0
|
|
|
|
Reply
|
Ian
|
2/18/2011 9:30:35 PM
|
|
Ian Collins <ian-news@hotmail.com> writes:
> On 02/19/11 10:20 AM, Edward Rutherford wrote:
>> I have been looking at some code which "for faster compilation" has ad hoc
>> declarations of some standard functions instead of including standard
>> headers.
>>
>> E.g.
>>
>> typedef unsigned int long size_t;
That's an odd way of declaring it. "unsigned int long" is legal, but
"unsigned long int" (or just "unsigned long") is much more common.
>> extern void* malloc(size_t);
>>
>> This feels to me like it's bad style, but I can't quite put my finger on
>> anything specific that's wrong with it.
>>
>> What do people think about this approach?
>
> It's terrible style
Yes.
> and renders the code non-conforming.
No. In fact, the standard specifically permits this. C99 7.1.4p2:
Provided that a library function can be declared without
reference to any type defined in a header, it is also permissible
to declare the function and use it without including its
associated header.
You can't declare fopen() this way, for example, because you need
<stdio.h> to get the correct declaration for type FILE.
Hmm. I suppose size_t is "type defined in a header", but as long
as the implementation actually does typedefs size_t as unsigned long
int, there shouldn't be any problem declaring it that way yourself.
Strictly speaking, the standard doesn't permit it, but I think that
only a deliberately perverse implementation would break it.
> It is not uncommon for system headers to use different types or even
> calling conventions for different environments (32/64 bit for example).
> Once you start adding your own declarations, you may well end up with
> code that at best won't link, at worst links but does weird things. A
> quick look at you systems headers should show you what I mean
You're guaranteed to be able to do this:
void *(*p)(size_t);
p = malloc;
and the implementation isn't permitted to play any tricks that would
break that.
Another issue, though, is that some standard function declarations
changed between C90 and C99 (the addition of "restrict" keywords,
for example). These changes have no effect on correct code,
but you could run into trouble if you try to mimic the standard
declarations yourself.
The idea, apparently, is to expend considerable manual effort
writing these declarations to reduce effort for the compiler.
Apart from being error-prone, IMHO this ignores the whole point of
what computers are for.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
|
|
0
|
|
|
|
Reply
|
Keith
|
2/18/2011 9:54:38 PM
|
|
Edward Rutherford <edward.p.rutherford79@REMOVETHIS.gmail.com> writes:
> I have been looking at some code which "for faster compilation" has
> ad hoc declarations of some standard functions instead of including
> standard headers.
Unless the system headers reside on a *very* slow storage medium,
like a NFS filesystem with locking issues, and then the problem should
be fixed elsewhere, that sound like a premature optimization to me.
> typedef unsigned int long size_t;
> extern void* malloc(size_t);
> This feels to me like it's bad style, but I can't quite put my
> finger on anything specific that's wrong with it.
If portability is not an issue, it may be brought to work. But I'll
guess that the time spent debugging subtle bugs caused by interaction
between code "optimized" in this way, and conformant code will
probably exceed the time saved in the first place.
> What do people think about this approach?
I would rewrite the code to include the proper header files.
--
/Wegge
Leder efter redundant peering af dk.*,linux.debian.*
|
|
0
|
|
|
|
Reply
|
Anders
|
2/18/2011 10:06:50 PM
|
|
On 02/19/11 10:54 AM, Keith Thompson wrote:
> Ian Collins<ian-news@hotmail.com> writes:
>> On 02/19/11 10:20 AM, Edward Rutherford wrote:
>>> I have been looking at some code which "for faster compilation" has ad hoc
>>> declarations of some standard functions instead of including standard
>>> headers.
>>>
>>> E.g.
>>>
>>> typedef unsigned int long size_t;
>
> That's an odd way of declaring it. "unsigned int long" is legal, but
> "unsigned long int" (or just "unsigned long") is much more common.
>
>>> extern void* malloc(size_t);
>>>
>>> This feels to me like it's bad style, but I can't quite put my finger on
>>> anything specific that's wrong with it.
>>>
>>> What do people think about this approach?
>>
>> It's terrible style
>
> Yes.
>
>> and renders the code non-conforming.
>
> No. In fact, the standard specifically permits this. C99 7.1.4p2:
>
> Provided that a library function can be declared without
> reference to any type defined in a header, it is also permissible
> to declare the function and use it without including its
> associated header.
>
> You can't declare fopen() this way, for example, because you need
> <stdio.h> to get the correct declaration for type FILE.
>
> Hmm. I suppose size_t is "type defined in a header", but as long
> as the implementation actually does typedefs size_t as unsigned long
> int, there shouldn't be any problem declaring it that way yourself.
> Strictly speaking, the standard doesn't permit it, but I think that
> only a deliberately perverse implementation would break it.
That was my point, if you declare a typedef like size_t in a different
way from the system headers, all bets are off.
>> It is not uncommon for system headers to use different types or even
>> calling conventions for different environments (32/64 bit for example).
>> Once you start adding your own declarations, you may well end up with
>> code that at best won't link, at worst links but does weird things. A
>> quick look at you systems headers should show you what I mean
>
> You're guaranteed to be able to do this:
> void *(*p)(size_t);
> p = malloc;
> and the implementation isn't permitted to play any tricks that would
> break that.
That's assuming you gave your malloc the correct return type. If you
had declared malloc as
int malloc(size_t);
Your code would link, but not behave as you had intended....
--
Ian Collins
|
|
0
|
|
|
|
Reply
|
Ian
|
2/18/2011 10:08:12 PM
|
|
On 2011-02-18, Anders Wegge Keller <wegge@wegge.dk> wrote:
> I would rewrite the code to include the proper header files.
Seconded.
Lemme tell you why.
I hate PINE. I hate it with a fiery, burning, and unending passion. Because,
you see, PINE (at least in the past) used to do this garbage. They REFUSED to
use standard headers. Instead, for each target, they'd carefully create what
they thought were probably the right declarations to use.
They were wrong.
This meant that, as soon as you tried PINE on a big-endian machine with a
64-bit filesystem, EVERYTHING blew up, data was lost, files were destroyed.
BECAUSE THEY WERE WRONG.
Note that their explanation was actually worse; apparently, there had once
existed a machine on which (they claim) the standard headers mis-declared
things, so they concluded it was "safer" to provide their own declarations.
There are two problems with this:
1. No one looking at that code would ever conclude that, had the author
of that code found a "bug" in a compiler, there was a legitimate basis for
thinking that the compiler had actually been at fault.
2. Breaking dozens of systems on the grounds that you once found one which
was broken is not a good trade-off.
Never do this.
To put this in perspective: I maintain a utility which works by intercepting
calls to the standard library and operating system and replacing them with
duplicates. That is to say, if you are running with this utility, and
you write:
FILE *fp = fopen(...);
your code will call *my* fopen, not the host environment one.
I use the prototype declarations from the standard headers. (It's fussier,
because I provide *definitions* of my own, which merely match signatures, but
I still let <stdio.h> provide the initial declaration of fopen().)
So, even if you really ARE writing your own versions of these functions,
it is still suicidally stupid not to use the standard headers for them.
Yes, in theory you might be able to do it correctly. You also might not.
-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
I am not speaking for my employer, although they do rent some of my opinions.
|
|
0
|
|
|
|
Reply
|
Seebs
|
2/18/2011 10:42:29 PM
|
|
On Fri, 2011-02-18, Anders Wegge Keller wrote:
> Edward Rutherford <edward.p.rutherford79@REMOVETHIS.gmail.com> writes:
>
>> I have been looking at some code which "for faster compilation" has
>> ad hoc declarations of some standard functions instead of including
>> standard headers.
....
>> typedef unsigned int long size_t;
>> extern void* malloc(size_t);
>
>> This feels to me like it's bad style, but I can't quite put my
>> finger on anything specific that's wrong with it.
>
> If portability is not an issue, it may be brought to work. But I'll
> guess that the time spent debugging subtle bugs caused by interaction
> between code "optimized" in this way, and conformant code will
> probably exceed the time saved in the first place.
Even if no such bugs appeared, I'd waste time *worrying* that this
weirdness caused the problem, for every real bug in the code.
/Jorgen
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
|
|
0
|
|
|
|
Reply
|
Jorgen
|
2/19/2011 12:48:13 AM
|
|
On 2/18/2011 4:20 PM, Edward Rutherford wrote:
> Hello
>
> I have been looking at some code which "for faster compilation" has ad hoc
> declarations of some standard functions instead of including standard
> headers.
>
> E.g.
>
> typedef unsigned int long size_t;
> extern void* malloc(size_t);
>
> This feels to me like it's bad style, but I can't quite put my finger on
> anything specific that's wrong with it.
>
> What do people think about this approach?
Bleaggh! (That's technical jargon with a meaning related to
"Yuck!" and "Puke!" and "Retch!" and "Ug-ugh-ugggh-BARF!")
It imperils the programmer's immortal soul by disobeying the
Fourth Commandment (http://www.lysator.liu.se/c/ten-commandments.html),
not even subtly or slightly but directly, openly, and flagrantly.
It's also wrong, R-O-N-G, wrong on any system where `size_t' is
not an alias for `unsigned long', but is some other type -- like
`unsigned int' or `unsigned long long' or `__builtin_size_t_type'.
I'm given to understand that Win64 is one such system, and there
are quite likely others.
Not only that, but it's a fornicating stupid thing to do.
Don't Do That.
--
Eric Sosman
esosman@ieee-dot-org.invalid
|
|
0
|
|
|
|
Reply
|
Eric
|
2/19/2011 4:11:18 AM
|
|
Ian Collins <ian-news@hotmail.com> writes:
> On 02/19/11 10:20 AM, Edward Rutherford wrote:
>> Hello
>>
>> I have been looking at some code which "for faster compilation" has ad hoc
>> declarations of some standard functions instead of including standard
>> headers.
>>
>> E.g.
>>
>> typedef unsigned int long size_t;
>> extern void* malloc(size_t);
>>
>> This feels to me like it's bad style, but I can't quite put my finger on
>> anything specific that's wrong with it.
>>
>> What do people think about this approach?
>
> It's terrible style and renders the code non-conforming.
You may not like the style, but technically speaking it is
conforming. Section 4, p 7.
|
|
0
|
|
|
|
Reply
|
Tim
|
2/21/2011 4:13:42 AM
|
|
Eric Sosman <esosman@ieee-dot-org.invalid> writes:
> On 2/18/2011 4:20 PM, Edward Rutherford wrote:
>> Hello
>>
>> I have been looking at some code which "for faster compilation" has ad hoc
>> declarations of some standard functions instead of including standard
>> headers.
>>
>> E.g.
>>
>> typedef unsigned int long size_t;
>> extern void* malloc(size_t);
>>
>> This feels to me like it's bad style, but I can't quite put my finger on
>> anything specific that's wrong with it.
>>
>> What do people think about this approach?
>
> Bleaggh! (That's technical jargon with a meaning related to
> "Yuck!" and "Puke!" and "Retch!" and "Ug-ugh-ugggh-BARF!")
>
> It imperils the programmer's immortal soul by disobeying the
> Fourth Commandment (http://www.lysator.liu.se/c/ten-commandments.html),
> not even subtly or slightly but directly, openly, and flagrantly.
>
> It's also wrong, R-O-N-G, wrong on any system where `size_t' is
> not an alias for `unsigned long', but is some other type -- like
> `unsigned int' or `unsigned long long' or `__builtin_size_t_type'.
> I'm given to understand that Win64 is one such system, and there
> are quite likely others.
>
> Not only that, but it's a fornicating stupid thing to do.
>
> Don't Do That.
Don't hold back, Eric - tell us what you really think. :)
|
|
0
|
|
|
|
Reply
|
Tim
|
2/21/2011 4:16:25 AM
|
|
On 2/18/2011 4:20 PM, Edward Rutherford wrote:
> Hello
>
> I have been looking at some code which "for faster compilation" has ad hoc
> declarations of some standard functions instead of including standard
> headers.
>
> E.g.
>
> typedef unsigned int long size_t;
> extern void* malloc(size_t);
>
> This feels to me like it's bad style, but I can't quite put my finger on
> anything specific that's wrong with it.
>
> What do people think about this approach?
Ick. Blech. Run away!
While malloc() is defined in 7.20.3.3 as:
void *malloc(size_t size);
the definition of size_t is implementation-defined. The only guarantee is
that it is "an unsigned integer type". There is absolutely no guarantee
that it is an "unsigned long", and forcing that definition onto your code is
guaranteed to to "bad things" on any platform where it is something not
bitwise compatible with such a type.
Now, I've been around long enough to remember when "faster compiler time"
was an issue. When "make program-name" might take 20 minutes, speeding it
up to 15 minutes could be considered a "good thing". However, saving a
fraction of a second off of a 30-second make is not worth the problems
caused by using your own (possibly incompatible) definitions for standard
functions.
--
Kenneth Brody
|
|
0
|
|
|
|
Reply
|
Kenneth
|
2/21/2011 5:09:54 PM
|
|
|
10 Replies
212 Views
(page loaded in 0.13 seconds)
Similiar Articles: C style question - comp.lang.cHello I have been looking at some code which "for faster compilation" has ad hoc declarations of some standard functions instead of including sta... Wiki on C++ tech screening questions - comp.lang.c++.moderated ...C style question - comp.lang.c C style question - comp.lang.c Or should I use char arrays and use C-style parsing?? Should I first load the ... Wiki on C++ tech screening ... another simple question - comp.emacsNewbie question about rotate a picture using OpenGL - comp ... simple question about MODEL matrix - comp.graphics.api.opengl ... another simple question - comp.emacs ... exact difference between C style and static_cast, const_cast ...C style question - comp.lang.c exact difference between C style and static_cast, const_cast ..... com/questions/28002/regular-cast-vs-static-cast-vs-dynamic-cast http ... glut and (Visual)C++ - comp.graphics.api.openglC style question - comp.lang.c glut and (Visual)C++ - comp.graphics.api.opengl The callback functions are static C-style functions, but they each get a pointer to ... We Wait For Thee: char16_t, char32_t. - comp.lang.c++.moderated ...C style question - comp.lang.c We Wait For Thee: char16_t, char32_t. - comp.lang.c++.moderated ... { The question concerns the two C++0x types char16_t and char32_t. -mod ... nitializing a static vector <> of integers (this static vectorI would like to use STL vector instead of a C-style array here: How would I ... This would be a great help if you can answer this question. sample code please ... extern typedef struct - comp.lang.cC style question - comp.lang.c typedef unsigned int long size_t; extern void* malloc(size_t); This feels to me like it's bad ... code and found a struct declared in the ... itoa() in Linux - comp.unix.programmerHi all, I'm using the itoa function in my C code but it does not compile in Linux ... Post Question | Groups | ... tuple and brace initializer - why not - comp.lang.c++.moderated ...C style question - comp.lang.c > > Not only that, but it's a fornicating stupid thing ... Usage of an array variables in initialization list - comp.lang ... good excuse ... Style question: #include - C / C++ - Bytes - Tech Commmunity ...Style question: #include. C / C++ Forums on Bytes. ... I have a program that uses a large lookup table, provided as a large array in the source: Style - comp.lang.c Frequently Asked QuestionsA: Kernighan and Ritchie, while providing the example most often copied, also supply a good excuse for disregarding it: The position of braces is less important ... 7/27/2012 3:08:23 PM
|