C style question

  • Follow


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:













7/27/2012 3:08:23 PM


Reply: