Re: Function definitions
Re: Function definitions
- Subject: Re: Function definitions
- From: Greg Herlihy <email@hidden>
- Date: Sun, 09 Apr 2006 14:48:57 -0700
- Thread-topic: Function definitions
On 4/8/06 6:58 PM, "Ondra Cada" <email@hidden> wrote:
> Greg,
>
> On 9.4.2006, at 3:22, Greg Herlihy wrote:
>
>> But just because the compiler does not require a function prototype
>> in this
>> situation does not mean that the compiler does not need a function
>> prototype.
>
> Nope, you are looking at it from the wrong perspective. The compiler
> does *not* need (neither require) a prototype indeed. This...
The function prototype is indeed needed if the code - as written - is to
compile correctly. The code as written is correct; the function prototype is
needed simply to ensure that the compiler compiles it correctly (that is,
produces a build that runs as the programmer expects).
Granted, there is an assumption that the programmer requires that any
program built by the compiler to have been compiled correctly. In fact, it
is further assumed that the programmer would prefer that the compiler build
nothing (and report an error), rather than build a program that does not run
as expected. And I think such an assumption would be safe to make for most
programmers.
>> 4 /tmp> >q.m
>> int sum(float a, float b) { return a+b; }
>> 5 /tmp> >w.m
>> #import <Cocoa/Cocoa.h>
>> int main() { printf("wow! %d\n",sum(5,5)); return 0; }
>> 6 /tmp> cc q.m w.m && ./a.out
>> wow! 8
>> 7 /tmp>
>
> ...is just a plain *programmer's fault*, for the proper code should
> have looked this:
>
> 21 /tmp> >q.m
> int sum(float a, float b) { return a+b; }
> 22 /tmp> >w.m
> #import <Cocoa/Cocoa.h>
> int main() { printf("wow! %d\n",sum(5.,5.)); return 0; }
> 23 /tmp> cc q.m w.m && ./a.out
> wow! 10
> 24 /tmp>
This revised code shows how easy it is to make mistakes in the absence of
function prototypes. The revised program now passes doubles as parameters
(instead of the int parameters in the original) - but still does not pass
the float parameters that sum() is actually expecting. So without function
prototypes, a correct call to sum would have to look like this:
sum(5.0f, 5.0f);
Passing any other type of parameter in this situation is technically an
error - but an error which the compiler cannot detect when no function
prototype for sum() has been provided.
By providing function prototypes, the programmer is freed of any (obviously
error-prone) obligation to call a function with type-exact parameters. The
presence of function prototypes means that the compiler will implicitly
convert any mismatched parameter types passed in function calls to the types
that function is expecting (or will lead to a compilation error if such a
required conversion cannot be performed implicitly).
So the bug in the original program is not the way in which sum() is called.
The bug is simply a failure to provide the function prototype for sum()
needed to convert the parameters passed in that function call to the types
expected. Furthermore, reconfiguring the compiler to require function
prototypes would have prevented this kind of oversight from compiling in the
first place.
> Of course, since it is extremely easy to fall for this kind of
> programmer's error, the compiler *allows* (!) you to use prototypes,
> and if you do so, it (a) casts for you properly, (b) checks for your
> typos (just as I've written previously, that were the first and
> second main reasons to use headers).
>
>> To return to the original question regarding whether it is in fact
>> necessary
>> to provide both function definitions in one file and matching function
>> declarations in another: the answer is that - were a C compiler
>> like a Java
>> compiler, that is, were it able to derive a set of function
>> declarations
>> from a set of function definitions - then the answer would be "no".
>> It would
>> not be necessary for a programmer to provide a "header" file for a
>> source
>> file - because the compiler could figure out on its own what such a
>> header
>> file would contain.
>>
>> Unfortunately, a C compiler does not produce header files, so the
>> programmer
>> has to create them by hand. And creating a header file is sheer
>> drudgery for
>> the programmer. After all, the programmer is doing nothing other than
>> providing the C compiler with the same set of information that the
>> compiler
>> could - were it a bit smarter - be able to figure out on its own.
>
> Just again you are taking it backwards -- here we get to the third
> main reason for having headers: they are excellent and priceless as a
> quick (and, properly commented, also as a thorough) API reference.
> It's one of main Java lacks that it does *not* have headers, and thus
> there is no nice and intuitive place to put API comments: sure, you
> can intersperse them in implementation, but then you have either to
> sift through all the code or to run something which does it for you
> (in the case of Javadoc with very poor and counter-intuitive results)
> before you can peep there for a quick ref how the API looks like. Not
> speaking of the fact that the ugly Java thing, having no headers,
> *bitterly* lacks the preprocessor, but that's another story.
This is getting off topic - but Java (unlike C++) has explicit support for
source code documentation (JavaDoc). So Java programmers do not have to sift
through source files for documentation. Instead, a Java programmer can
generate documentation automatically from specially-formatted comments
embedded within Java source files. Tools do exist that recognize JavaDoc
comments placed in C++ source files.
> To sum it all up:
>
> (i) the C (and ObjC) compiler does not *need* function or message
> prototypes (making so headers "superfluous" far as functions and
> messages are concerned; you cannot do without them for global
> variable references, macros, enums, typedefs, struct/union
> declarations, inlines, and so forth);
If the program makes function calls that rely on implicit type conversions
for the passed parameters (or expects any function call with a parameter
that cannot be converted to cause a compile-time, and not a run-time,
error), then function prototypes are needed to meet both the program's (and
the programmer's) expectations. And only a program that has been compiled
correctly can really be called a success - any other outcome (whether it
produces a build or not) - is really just some kind of failure.
> (ii) though, the compiler *allows* us to use function and message
> prototypes
> - to be warned when we make a typo;
> - to be relieved from the burden of casting properly manually;
> and we would be fools if we did not exploit this enormous advantage;
Agreed. Which is why XCode should require function prototypes by default -
just as CodeWarrior did.
> (iii) headers, properly documented, also can serve as an *excellent*
> API reference, which is just another reason to keep them and to write
> them well.
Comments in headers are appropriate input into a documentation generation
system, such as Doxygen. But headers should not serve as the primary vehicle
for presenting source code documentation. Having program documentation
strewn over multiple header files without the benefit of a clear
organization is not the ideal way to provide documentation to a programmer.
Greg
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden