prototypes

D

DevarajA

If a function is visible everywhere, even out the file where it is
declared and defined, why should i write prototypes?
 
D

DevarajA

DevarajA ha scritto:
If a function is visible everywhere, even out the file where it is
declared and defined, why should i write prototypes?

I've just read that they're used for type checking when calling external
functions. Is that true?
 
O

osmium

DevarajA ha scritto:

I've just read that they're used for type checking when calling external
functions. Is that true?

The thing described by the OP (who,oddly enough, has the same nym as you) is
not an external function. He said it was *visible*. C does compiling in a
forward direction and it must know the argument types when it compiles. So
if you do the physical definition prior to the first usage you don't need a
prototype. This is sometimes called "Pascal style". The prototypes for
external functions are usually in a visible header file.
 
D

DevarajA

osmium ha scritto:
The thing described by the OP (who,oddly enough, has the same nym as you) is
not an external function. He said it was *visible*. C does compiling in a
forward direction and it must know the argument types when it compiles. So
if you do the physical definition prior to the first usage you don't need a
prototype. This is sometimes called "Pascal style". The prototypes for
external functions are usually in a visible header file.

so why this works and only gives "implicit declaration" warnings?

int main()
{
a(8,9);
b(9,9.5);
c(9.5,10);
return 0;
}
int a(int x, int y){return 0;}
int b(int x, double y){return 0;}
int c(double x, int y){return 0;}
 
O

osmium

DevarajA said:
so why this works and only gives "implicit declaration" warnings?

int main()
{
a(8,9);
b(9,9.5);
c(9.5,10);
return 0;
}
int a(int x, int y){return 0;}
int b(int x, double y){return 0;}
int c(double x, int y){return 0;}

There was a time when something called K&R C was a more or less de facto
standard. Before there was a real standard. It assumed that everything was
int. Your compiler is in a mode such that it accepts the old dialect.
 
D

DevarajA

osmium ha scritto:
:




There was a time when something called K&R C was a more or less de facto
standard. Before there was a real standard. It assumed that everything was
int. Your compiler is in a mode such that it accepts the old dialect.

So for that old standard a call to a undeclared function f1 is an
implicit declaration (as int f1(...))?
 
J

John Bode

DevarajA said:
If a function is visible everywhere, even out the file where it is
declared and defined, why should i write prototypes?

You need to have a prototype declaration in scope if the function is
being called before it has been defined. If you have all your
functions in the same file, and you define each function before it is
used, you don't need a prototype declaration.

Example:

double foo(int x, float y)
{
...
}

char *bar(void)
{
...
double g = foo(1, 2.0);
}

int main(void)
{
char *msg = bar();
...
}

Since the functions are defined (using prototype syntax) before they
are called, the compiler is able to verify that the return types and
the number and types of arguments match between the definition and
call.

Now, suppose the order were reversed:

int main (void)
{
char *msg = bar();
...
}

char *bar(void)
{
double g = foo(1, 2.0);
...
}

double foo(int x, float y);
{
...
}


When the compiler sees the call to bar(), it has no prior definition or
declaration of bar in scope, so it assumes bar() returns int, and does
no parameter checking. In this case, the compiler should issue a
diagnostic since it thinks you're trying to assign an int value to a
char *. Similarly, when the compiler first sees the call to foo(), it
assumes that foo() returns int, does no checking on the parameters, and
applies the default type promotions (IIRC, without a definition or
declaration in scope, 2.0 will be passed as a double instead of a
float). Again, you'll get a warning about trying to assign an int to a
double.
 
E

Eric Sosman

osmium said:
The thing described by the OP (who,oddly enough, has the same nym as you) is
not an external function. He said it was *visible*. C does compiling in a
forward direction and it must know the argument types when it compiles. So
if you do the physical definition prior to the first usage you don't need a
prototype. This is sometimes called "Pascal style". The prototypes for
external functions are usually in a visible header file.

There's some evidence of confusion here, so to clear
the air: A prototype is the parenthesis-enclosed list of
types or type/argument pairs that appears in a function
declaration. It is possible to declare a function with
a prototype

double func(double, int, const char*);

or without a prototype

double func();

Equally, it is possible to define a function with a
prototype

double func(double x, int i, const char *s) {
return x + i * strlen(s);
}

or without a prototype

double func(x, i, s)
double x;
int i;
const char *s;
{
return x + i * strlen(s);
}

DevarajA and osmium seem to be saying "prototype" when
what they actually mean is "declaration." osmium's point
is that a function definition is also a declaration (though
the opposite is clearly not true), and is really not about
prototypes at all.
 
E

Eric Sosman

John said:
If a function is visible everywhere, even out the file where it is
declared and defined, why should i write prototypes?


You need to have a prototype declaration in scope if the function is
being called before it has been defined. [...]

No: You need a declaration, but the declaration is not
required to provide a prototype. (Under C90 rules, even
the declaration is sometimes optional.)

Prototypes are a Good Thing; I cannot think of a case
where a prototype-less declaration wouldn't be improved by
adding a prototype. However, the only time a prototype is
actually required is when the function has a variable-length
argument list. All fixed-length prototypes can be omitted,
if you've got masochistic tendencies and are willing to suffer
opprobrium from others who work with your awful code.
 
J

John Bode

Eric said:
John said:
If a function is visible everywhere, even out the file where it is
declared and defined, why should i write prototypes?


You need to have a prototype declaration in scope if the function is
being called before it has been defined. [...]

No: You need a declaration, but the declaration is not
required to provide a prototype. (Under C90 rules, even
the declaration is sometimes optional.)

Prototypes are a Good Thing; I cannot think of a case
where a prototype-less declaration wouldn't be improved by
adding a prototype. However, the only time a prototype is
actually required is when the function has a variable-length
argument list. All fixed-length prototypes can be omitted,
if you've got masochistic tendencies and are willing to suffer
opprobrium from others who work with your awful code.

You're right. That first sentence should be amended to, "you need to
have a declaration in scope (preferably using prototype syntax in favor
of the old K&R-style syntax) ..."
 
F

Flash Gordon

DevarajA said:
osmium ha scritto:

It was not removed from the C89 standard, only deprecated.
So for that old standard a call to a undeclared function f1 is an
implicit declaration (as int f1(...))?

No, definitely not. It assumes are return type of in and a FIXED number
and types of arguments (after they have undergone the default argument
promotions) based on the first call it sees. Although this works if you
get it exactly right, it does not work if:
1) The function returns something other than int
2) You don't get the list of arguments right
3) the functions has varargs (, ...) parameters
4) The function takes parameters of types that will be promoted (e.g. char)

The compiler does not have to diagnose (generate error or warning) for
ANY of these problems. So you should always make sure you have the
correct prototype in scope.
 
E

Emmanuel Delahaye

DevarajA wrote on 19/07/05 :
If a function is visible everywhere, even out the file where it is declared
and defined, why should i write prototypes?

You mean separated prototypes ? To be sure that you are using the
function correctily (type and number of parameters essentially)

The Good Way(c) is

declare the function in a header (.h) as a separated prototype:

/* f.h */
int f(char const *s);

define the function in a source file (.c) and include the prototype
(for consistency):

/* f.c */
#include "f.h"

int f(char const *s)
{
}

Include the header (hence the prototype) each time you use the function
elswhere:

/* x.c */
#include "f.h"

....
{
int a = f ("123");
}

Of course the header, like any header, is protected against multiple
inclusions:

#ifndef H_F
#define H_F
....
#endif /* guard */



--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"Mal nommer les choses c'est ajouter du malheur au
monde." -- Albert Camus.
 
M

Mark McIntyre

If a function is visible everywhere, even out the file where it is
declared and defined, why should i write prototypes?

Having external linkage ie being visible to the linker everywhere does
not mean also visible to the compiler. Nor that it knows the types of
the arguments or even the function's return type. You need to
prototype the fn in order for the compiler to know that.
 
D

Dave Thompson

It was not removed from the C89 standard, only deprecated.
Nit: Implicit int, and implicit function declaration, which is
slightly different but related and is what is actually at issue here,
were _not_ deprecated in C89/90, but were deleted in C99.
_Nonprototype_ declarations and definitions of functions, aka K&R1 or
old-style, _were_ deprecated (actually, called obsolescent) in C89/90
and are still obsolescent but still present in C99.
No, definitely not. It assumes are return type of in and a FIXED number
and types of arguments (after they have undergone the default argument
promotions) based on the first call it sees. Although this works if you
get it exactly right, it does not work if:
1) The function returns something other than int
2) You don't get the list of arguments right
3) the functions has varargs (, ...) parameters
4) The function takes parameters of types that will be promoted (e.g. char)

It is not required to work if you get these wrong, but it _might_.

In particular on many systems, but not all, variadic and nonvariadic
calls are compatible so violating 3 won't fail; and on I think most
systems the calling sequence promotes narrow types even where C
doesn't so violating 4 at least for integers won't actually fail.
The compiler does not have to diagnose (generate error or warning) for
ANY of these problems. So you should always make sure you have the
correct prototype in scope.

The implementation is not required to diagnose wrong nonprototyped
calls, and the compiler in particular is almost never able to; in some
rare systems the linker can. Historically there was a separate tool,
lint, which did check, and there are still versions around, but using
prototypes is usually easier and certainly more standard.

Note particularly the phrasing 'correct prototype'. The compiler will
check and conform calls against the prototype provided, but cannot by
itself check the prototype declaration against the definition if in a
different translation unit ~ source file. For this reason if you
follow the normal practice of implementing a module (one or several
related 'public' functions, perhaps plus other stuff) in a foo.c file
and putting the declarations therefor in foo.h for other modules like
bar.c to #include, you should also #include foo.h in foo.c. This seems
redundant, since the compiler knows the types from the definitions,
but it will (is required to) check that the types in the definition(s)
are compatible with those in the declaration(s) that clients are
using; if you change the definition but forget to update the
declaration, or vice versa (IME less likely), this will catch it.

- David.Thompson1 at worldnet.att.net
 

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,767
Messages
2,569,570
Members
45,045
Latest member
DRCM

Latest Threads

Top