function definitions

B

borophyll

I don't understand the difference between these two declarations

int foo(char a, char b)
{
...
}

int foo(a, b)
char a, b;
{
...
}

What is the usefulness of the second form? Is there any difference?

Secondly, I notice that if a declaration list is not included
following an identifier list, gcc warns that the types of all the
identifiers will default to int. Is there somewhere in the spec that
states a default type given to identifiers if it is not explicit? If
so, can someone please give me a pointer to the section? Or is this
just a gcc extension/assumption?

Regards,
B.
 
K

Keith Thompson

I don't understand the difference between these two declarations

int foo(char a, char b)

This is a prototype.
{
...
}

int foo(a, b)
char a, b;

This is an old-style declaration, sometimes called "K&R style" because
it's used in the first edition K&R (Kernighan & Ritchie, _The C
Programming Language_.
{
...
}

What is the usefulness of the second form? Is there any difference?

K&R style function declarations are effectively obsolescent, though
they're still legal. Prior to the first ANSI C standard, in 1989,
they were the only form available, but the standardization committee
borrowed the first form (prototypes) from an early version of C++.

It's useful to recognize K&R style declarations when you encounter
them in old code, but you should never use them in new code (unless,
for some strange reason, you need to support an ancient compiler).

In this particular case, there's another difference. Due to argument
promotions, the parameters in the K&R declaration are really of type
int. The parameters in the prototype really are of type char.
Secondly, I notice that if a declaration list is not included
following an identifier list, gcc warns that the types of all the
identifiers will default to int. Is there somewhere in the spec that
states a default type given to identifiers if it is not explicit? If
so, can someone please give me a pointer to the section? Or is this
just a gcc extension/assumption?

Implicit int was removed from the language in the 1999 standard (but
few compilers fully support C99, and most or all compilers still
permit implicit int in some mode).

Don't use it. The time you save by not typing "int" isn't worth the
headache of wondering whether it's legal to leave it out.
 
J

John Bode

I don't understand the difference between these two declarations

int foo(char a, char b)
{
...

}

int foo(a, b)
char a, b;
{
...

}

What is the usefulness of the second form? Is there any difference?

The second form is outdated, and should no longer be used.
Secondly, I notice that if a declaration list is not included
following an identifier list, gcc warns that the types of all the
identifiers will default to int. Is there somewhere in the spec that
states a default type given to identifiers if it is not explicit? If
so, can someone please give me a pointer to the section? Or is this
just a gcc extension/assumption?

I can't remember off the top of my head, but it doesn't matter,
because you're not going to use it.
 
B

borophyll

I don't understand the difference between these two declarations

int foo(char a, char b)
{
...

}

int foo(a, b)
char a, b;
{
...

}

What is the usefulness of the second form? Is there any difference?

Secondly, I notice that if a declaration list is not included
following an identifier list, gcc warns that the types of all the
identifiers will default to int. Is there somewhere in the spec that
states a default type given to identifiers if it is not explicit? If
so, can someone please give me a pointer to the section? Or is this
just a gcc extension/assumption?

Regards,
B.

Thanks for the info, I guessed it was an old obsolescent form, and had
this confirmed after rereading it and seeing the footnote which
directed me to the following two sections:

6.11.6 Function declarators
The use of function declarators with empty parentheses (not prototype-
format parameter type declarators) is an obsolescent feature.

6.11.7 Function definitions
The use of function definitions with separate parameter identifier and
declaration lists (not prototype-format parameter type and identifier
declarators) is an obsolescent feature.

Reading 6.11.6 reads to me that function declarators with an empty
parameter list will become obsolete, except if the function declarator
is a prototype. In other words, you can have

int foo();

but not

int foo(){ ... }

which should be written as int foo(void){ ... }. Is this correct?
and if so, why do we allow parameterless prototypes? What are they
useful for? The only reason I can think is to link to some external
definition of a function whose parameters are unknown, but in what
case would you want to call a function with an unknown number and type
of parameters?

Regards,
B.
 
P

pete

Keith said:
This is a prototype.


This is an old-style declaration, sometimes called "K&R style" because
it's used in the first edition K&R (Kernighan & Ritchie, _The C
Programming Language_.


K&R style function declarations are effectively obsolescent, though
they're still legal. Prior to the first ANSI C standard, in 1989,
they were the only form available, but the standardization committee
borrowed the first form (prototypes) from an early version of C++.

It's useful to recognize K&R style declarations when you encounter
them in old code, but you should never use them in new code (unless,
for some strange reason, you need to support an ancient compiler).

In this particular case, there's another difference. Due to argument
promotions, the parameters in the K&R declaration are really of type
int. The parameters in the prototype really are of type char.

What do you mean?
Argument promotions apply to arguments, not parameters.

/* BEGIN new.c */

#include <stdio.h>

int foo(a, b)
char a, b;
{
return printf("sizeof a is %u\n", (unsigned)sizeof a);
}

int main(void)
{
foo(0,0);
return 0;
}

/* END new.c */
 
K

Keith Thompson

pete said:
Keith said:
I don't understand the difference between these two declarations

int foo(char a, char b)

This is a prototype.
{
...
}

int foo(a, b)
char a, b;

This is an old-style declaration, sometimes called "K&R style" because
it's used in the first edition K&R (Kernighan & Ritchie, _The C
Programming Language_.
[...]
In this particular case, there's another difference. Due to argument
promotions, the parameters in the K&R declaration are really of type
int. The parameters in the prototype really are of type char.

What do you mean?
Argument promotions apply to arguments, not parameters.

/* BEGIN new.c */

#include <stdio.h>

int foo(a, b)
char a, b;
{
return printf("sizeof a is %u\n", (unsigned)sizeof a);
}

int main(void)
{
foo(0,0);
return 0;
}

/* END new.c */

(The above program prints "sizeof a is 1".)

You're right, I was confused. I remembered that mechanically
converting old-style declarations to prototypes can cause problems for
parameters of integer types narrower than int and floating-point types
narrower than double, but I drew the wrong conclusion.

If you pass arguments of type char to foo, they'll be promoted to int
(because the parameter type information isn't available at the point
of the call), and then reconverted back to char. Because of this,
back in the Old Days, parameters of types that are subject to
promotion were generally discouraged.

With a prototype, char arguments are simply passed and stored as type
char.

My poor excuse is that I haven't had to use old-style function
declarations in a long time. I *think* I've got it right this time.
 
C

Christopher Benson-Manica

[comp.lang.c] Keith Thompson said:
K&R style function declarations are effectively obsolescent, though
they're still legal.

And not even deprecated, right? I suppose one day C will lose enough
of these legacy features to make the IOCCC obsolete, but I suspect
I will be long dead (and I'm 27 <g>).
 
K

Keith Thompson

Christopher Benson-Manica said:
[comp.lang.c] Keith Thompson said:
K&R style function declarations are effectively obsolescent, though
they're still legal.

And not even deprecated, right? I suppose one day C will lose enough
of these legacy features to make the IOCCC obsolete, but I suspect
I will be long dead (and I'm 27 <g>).

C99 6.11.7:

The use of function definitions with separate parameter identifier
and declaration lists (not prototype-format parameter type and
identifier declarators) is an obsolescent feature.

The introduction to the standard says:

Certain features are obsolescent, which means that they may be
considered for withdrawal in future revisions of this
International Standard. They are retained because of their
widespread use, but their use in new implementations (for
implementation features) or new programs (for language [6.11] or
library features [7.26]) is discouraged.
 
D

David Thompson

On Wed, 26 Sep 2007 01:40:42 -0000, (e-mail address removed) wrote:
Thanks for the info, I guessed it was an old obsolescent form, and had
this confirmed after rereading it and seeing the footnote which
directed me to the following two sections:

6.11.6 Function declarators
The use of function declarators with empty parentheses (not prototype-
format parameter type declarators) is an obsolescent feature.

6.11.7 Function definitions
The use of function definitions with separate parameter identifier and
declaration lists (not prototype-format parameter type and identifier
declarators) is an obsolescent feature.

Reading 6.11.6 reads to me that function declarators with an empty
parameter list will become obsolete, except if the function declarator
is a prototype. In other words, you can have

int foo();

but not

int foo(){ ... }

which should be written as int foo(void){ ... }. Is this correct?

No. In C, a function declarator with empty parentheses is not a
prototype. The parenthesised(!) clauses in 6.11.6,7 are (additional)
explanations of the statements NOT limitations on their applicability.
<OT> C++ is different: K&R1 style is dropped, ALL function declarators
have prototype syntax and semantics, and empty parentheses mean no
parameters. In C++ you MAY also use (void) to mean explicitly zero
parameters, in C you MUST use it to get that meaning. </>

<snip points that depend on false assumption>

Nit: it doesn't actually say they 'will' become obsolete, or more
specifically that they will be deleted. It says they _may_, and some
people believe they _should_, but AFAICT the standards process does
not allow a binding commitment to future action. But for the reasons
already discussed, you should avoid them even if they aren't deleted.

- formerly david.thompson1 || achar(64) || 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,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top