Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

func( ) and func (void) question...

0 views
Skip to first unread message

Regis

unread,
Apr 17, 2000, 3:00:00 AM4/17/00
to

Hi,

I comes from the c++ world where :
func(/*nothing*/) and func (void)
have the same meaning.

[4 lines leaved empty to fill with "off-topic" flames here :))]


However, in C, func(void) means a function with exactly zero args
whereas func() means a function with an "unspecified" number of args.
For variadic functions, we already have func (int n, ...) which works
fine,
so I don't see clearly the usefullness of func( ) in C.
Any short example of usefull-use is welcomed.
...and what is the mechanism (if exists) to access the so-called
"unspecified" args in func ( ) ?

Regis

Richard Bos

unread,
Apr 17, 2000, 3:00:00 AM4/17/00
to
Regis <re...@info.unicaen.fr> wrote:

> However, in C, func(void) means a function with exactly zero args
> whereas func() means a function with an "unspecified" number of args.
> For variadic functions, we already have func (int n, ...) which works
> fine,
> so I don't see clearly the usefullness of func( ) in C.

Neither do I, but it's there for historical reasons; and, for all I
know, for none other.

Richard

Christian Bau

unread,
Apr 17, 2000, 3:00:00 AM4/17/00
to
In article <38FACF6E...@info.unicaen.fr>, Regis
<re...@info.unicaen.fr> wrote:

> Hi,
>
> I comes from the c++ world where :
> func(/*nothing*/) and func (void)
> have the same meaning.
>
> [4 lines leaved empty to fill with "off-topic" flames here :))]
>
>
>
>

> However, in C, func(void) means a function with exactly zero args
> whereas func() means a function with an "unspecified" number of args.
> For variadic functions, we already have func (int n, ...) which works
> fine,
> so I don't see clearly the usefullness of func( ) in C.

It is not useful, it is history...

C compilers will happily compile function calls even if they have never
seen a declaration of the function (many compilers will give a warning if
that happens). If you are (rightfully) worried that this will cause
trouble, then you would put a prototype into the header file. Now if you
are too lazy to find out the exact argument list of the function, you add
a prototype like "double myfunction ()".

That means you get 50% of the type checking and miss the other 50%. Better
than nothing, but not nearly as good as a correct prototype.

Regis

unread,
Apr 17, 2000, 3:00:00 AM4/17/00
to
Christian Bau wrote:

> It is not useful, it is history...

So, what style should be prefered in ansi-C between:
1: void func ( ) { printf ("blablabla\n"); }
2: void func (void) { printf ("blablabla\n"); }

Regis

Chris Mears

unread,
Apr 17, 2000, 3:00:00 AM4/17/00
to

Number 2.


--
Chris Mears

cme...@bigpond.com
ICQ: 36697123

C-FAQ: http://www.eskimo.com/~scs/C-faq/top.html

Eric Amick

unread,
Apr 17, 2000, 3:00:00 AM4/17/00
to
Regis <re...@info.unicaen.fr> wrote:
> Christian Bau wrote:
>
>> It is not useful, it is history...

> So, what style should be prefered in ansi-C between:
> 1: void func ( ) { printf ("blablabla\n"); }
> 2: void func (void) { printf ("blablabla\n"); }

Number 2 is better, but you should note that the two are equivalent in the
context of a function definition. Unless the latest standard has changed
it, the distinction between () and (void) applies only to function
declarations.

--
Eric Amick
Columbia, MD
eam...@clark.net

Regis

unread,
Apr 17, 2000, 3:00:00 AM4/17/00
to
Eric Amick wrote:

> > So, what style should be prefered in ansi-C between:
> > 1: void func ( ) { printf ("blablabla\n"); }
> > 2: void func (void) { printf ("blablabla\n"); }
>
> Number 2 is better, but you should note that the two are equivalent in the
> context of a function definition. Unless the latest standard has changed
> it, the distinction between () and (void) applies only to function
> declarations.

Perhaps in theory, but in practice:

Code 1:
#include <stdio.h>
void func (void ) { printf ("blablabla\n"); }
int main () { func (1,2,3); return 0; }

Code 2:
#include <stdio.h>
void func () { printf ("blablabla\n"); }
int main () { func (1,2,3); return 0; }

With my compiler in ansi-mode and full warnings
(gcc -W -Wall -ansi -pedantic),
the source 2 compiles without any warning
whereas source 1 produces (as it should)
the following error:

In function `main':
too many arguments to function `func'

However, I don't know if gcc is fully ansi-compliant.
Regis

Mal Kay

unread,
Apr 17, 2000, 3:00:00 AM4/17/00
to
Regis wrote:
....

> For variadic functions, we already have func (int n, ...) which works
> fine,
> so I don't see clearly the usefullness of func( ) in C.

func() can't be used for the declaration of a variadic function,
only for function with a fixed (but undeclared) set of arguments
and types.

Malcolm Kay

Gergo Barany

unread,
Apr 17, 2000, 3:00:00 AM4/17/00
to
Regis <re...@info.unicaen.fr> wrote:
> Christian Bau wrote:
>
> > It is not useful, it is history...
>
> So, what style should be prefered in ansi-C between:
> 1: void func ( ) { printf ("blablabla\n"); }
> 2: void func (void) { printf ("blablabla\n"); }

2a: void func(void) { puts("blablabla"); }

Gergo

--
Two is company, three is an orgy.

Joe Maun

unread,
Apr 17, 2000, 3:00:00 AM4/17/00
to
Eric Amick wrote:
>
> Regis <re...@info.unicaen.fr> wrote:
> > Christian Bau wrote:
> >
> >> It is not useful, it is history...
>
> > So, what style should be prefered in ansi-C between:
> > 1: void func ( ) { printf ("blablabla\n"); }
> > 2: void func (void) { printf ("blablabla\n"); }
>
> Number 2 is better, but you should note that the two are equivalent in the
> context of a function definition. Unless the latest standard has changed

They are not equivalent. 2: is a prototype, while 1: is not. This is
true regardless of whether they are definitions, or declarations.

--
Joe

Regis

unread,
Apr 17, 2000, 3:00:00 AM4/17/00
to
Joe Maun wrote:

> > > 1: void func ( ) { printf ("blablabla\n"); }
> > > 2: void func (void) { printf ("blablabla\n"); }
> >
> > Number 2 is better, but you should note that the two are equivalent in the
> > context of a function definition. Unless the latest standard has changed
>
> They are not equivalent. 2: is a prototype, while 1: is not. This is
> true regardless of whether they are definitions, or declarations.

Interesting.
I always thought a prototype was the sequence :
-> a return type
-> a func name
-> a list of typed paramaters (optionally named)
-> with eventually an ellipsis (...)
but the body was not part of it.

So for me, a definition was not a prototype.
Could you please tell me the precise def of a prototype ?

Regis

Richard Heathfield

unread,
Apr 17, 2000, 3:00:00 AM4/17/00
to

A definition /includes/ a prototype, and also includes a body.

> Could you please tell me the precise def of a prototype ?

Surely. From n869 6.2.1:

A function prototype is a declaration of a function that declares the
types of its parameters.


--

Richard Heathfield

"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.

C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
29 K&R Answers: http://users.powernet.co.uk/eton/kandr2/index.html (68
to go)

mike burrell

unread,
Apr 17, 2000, 3:00:00 AM4/17/00
to
Richard Heathfield <bin...@eton.powernet.co.uk> wrote:
> A definition /includes/ a prototype, and also includes a body.

unless it doesn't. it includes a declaration.

--
/"\ m i k e b u r r e l l
\ / ASCII RIBBON CAMPAIGN mik...@home.com
X AGAINST HTML MAIL
/ \

Chris Torek

unread,
Apr 17, 2000, 3:00:00 AM4/17/00
to
>Richard Heathfield <bin...@eton.powernet.co.uk> wrote:
>> A definition /includes/ a prototype, and also includes a body.

In article <VuJK4.74157$l41.2...@news1.sshe1.sk.home.com>


mike burrell <mik...@home.com> writes:
>unless it doesn't. it includes a declaration.

Right.

To enumerate, there are four things you can write, with regards
to declaring and/or defining functions:

- old-style declaration
- old-style definition
- prototype declaration
- prototype definition

The "old style" versions are available in C89 for compatibility with
"C as she was wrote before the Standard", as it were. They look like:

/* old-style declaration */
char *blort();

/* old-style definition */
char *blort(zog, frammible)
char *zog;
int frammible;
{
/* some code goes here */
return buf;
}

There are special constraints on the argument types for functions
declared and defined using this ancient K&R-1 style: the number of
arguments must be fixed, and each argument actually has a type that
is "pre-widened": i.e., none of char, signed char, unsigned char,
short, unsigned short, and float are really themselves. More on
this in a moment.

A prototype looks exactly like an old-style declaration except that
it has a list of types, and optional names, inside the parentheses:

char *blort(char *, int); /* prototype */

In order to distinguish between "prototype declaration of function
with no arguments" and "old-style declaration of function, arguments
simply not listed", C uses the otherwise-silly "(void)" notation:

int rand(void); /* also a prototype */

Since C++ has no historical base with which it wants to be compatible
(C++ does have various historical bases, but just arbitrarily becomes
incompatible every now and then instead :-) ), it does not need this
bit of syntactic ugliness.

A prototype definition is, of course, just a prototype declaration
followed by the actual code for the function instead of a semicolon:

char *blort(char *zog, int frammible) {
/* same code */
return buf;
}

You may mix prototype declarations and old-style defintions, or
old-style declarations and prototype definitions, if you wish. In
this case, however, you must be aware of those special constraints.
A function defined this way:

int shark(x)
char x;
{

/* the letter 'S' stands for a shark */
return x == 'S';
}

actually takes an "int", not a "char", because "char" is widened
to "int" by the default argument promotion rules. Thus, the correct
prototype is:

int shark(int x);

This is true even though "x" inside the old-style "shark" has type
char, so that "&x" has type "char x" -- the compiler is obliged to
promote arguments to shark(), then, inside shark(), act as if the
function had been defined as:

int shark(int arg_x) {
char x = arg_x;
... same code as before ...
}

This promotion and demotion tends to be cheap or even free (on some
systems, it just amounts to using only low bytes of the argument
registers inside the function), so many compilers do it all the
time, not just for old-style definitions.

Where this gets really tricky is when I give you some function that
has been lying around since Jimmy Carter was the president of the US
and is defined like this:

int xxioctl(dev, cmd, data)
dev_t dev;
int cmd;
char *data;
{
... some code here ...
}

What is the correct prototype for xxioctl()? I will tell you that
dev_t is a typedef for some sort of non-widened type, so that it is
*not* "int xxioctl(dev_t, int, char *)" -- dev_t is something like
short, unsigned short, or float.

Is it:

int xxioctl(int, int, char *);

or is it:

int xxioctl(unsigned int, int, char *);

or is it:

int xxioctl(double, int, char *);

? If I tell you that dev_t is definitely "unsigned short", you
can drop the last possibility, but what of the remaining two? (Hint:
you then need to know whether your -- or my -- implementation has
USHRT_MAX > INT_MAX.)

As long as you always use the newfangled (only 10 or so years old)
prototype definitions, you can always write a prototype declaration
easily, so this is generally your best bet.
--
In-Real-Life: Chris Torek, Berkeley Software Design Inc
El Cerrito, CA, USA Domain: to...@bsdi.com +1 510 234 3167
http://claw.bsdi.com/torek/ (not always up) I report spam to abuse@.

Richard Heathfield

unread,
Apr 17, 2000, 3:00:00 AM4/17/00
to
mike burrell wrote:
>
> Richard Heathfield <bin...@eton.powernet.co.uk> wrote:
> > A definition /includes/ a prototype, and also includes a body.
>
> unless it doesn't. it includes a declaration.

Er, yes. You've taken me out of context. Please put me back in
immediately! :-)

mike burrell

unread,
Apr 17, 2000, 3:00:00 AM4/17/00
to
Chris Torek <to...@elf.bsdi.com> wrote:
>>Richard Heathfield <bin...@eton.powernet.co.uk> wrote:
>>> A definition /includes/ a prototype, and also includes a body.

> In article <VuJK4.74157$l41.2...@news1.sshe1.sk.home.com>


> mike burrell <mik...@home.com> writes:
>>unless it doesn't. it includes a declaration.

> Right.

> To enumerate, there are four things you can write, with regards
> to declaring and/or defining functions:

> - old-style declaration
> - old-style definition
> - prototype declaration
> - prototype definition

hmm very interesting stuff. BTW even in the K&R days, a function
*definition* that didn't take any arguments would be a clue to the compiler
that it didn't take any arguments (duh). this might not have had much
relevance in the K&R days, but in the ANSI days, this would be a clue that
the compiler could construct its own prototype. e.g.:

1: #include <stdio.h>
2:
3: int foo() { return 3; }
4:
5: int main() { printf("%d\n", foo(5); }

it wouldn't take much for the compiler on line 5 to say "wait a second; i
just compiled this function a few seconds ago (i'm a really slow compiler)
and it didn't take any arguments then. hmmmmm....." the compiler could
even "manually" add its own prototype if it needed:

int foo() { return 3; }

"woah that's not a prototype! but it's a definition, so i can
figure out how to make my own prototype!" so then the compiler can
translate that piece of code into:

int foo(void); int foo() { return 3; }

before compiling it.

and likewise:

int foo(a, b) int a; int b; { return a + b; }

the compiler could tranlate it into:

int foo(int, int); int foo(a, b) int a; int b; { return a + b; }

before compiling it.

all is good, ja? i guess i'm saying that i can't think of any good reason
for the standard not to say that definition == prototype.

Chris Torek

unread,
Apr 17, 2000, 3:00:00 AM4/17/00
to
In article <MdMK4.74172$l41.2...@news1.sshe1.sk.home.com>
mike burrell <mik...@home.com> writes:
>... BTW even in the K&R days, a function *definition* that didn't take

>any arguments would be a clue to the compiler that it didn't take any
>arguments (duh). ... the compiler could even "manually" add [a correct]
>prototype [on seeing any old-style definition].

This would make lots of sense. Unfortunately, the (C89 anyway)
standard does not require compilers to do this. A few (well, gcc
at least, with the right flags) actually track the "implied prototype"
formed by an old-style declaration and will warn you if you goof
this up later:

int sum(a, b) int a, b; { return a + b; }
void x() {
int sum(double, double);
}

provokes diagnostics like this:

stdin:3: prototype for `sum' follows and argument 1
stdin:1: doesn't match non-prototype definition here

but this is a "quality of implementation" issue.

Morris M. Keesan

unread,
Apr 18, 2000, 3:00:00 AM4/18/00
to
On Mon, 17 Apr 2000 22:27:56 GMT, mike burrell <mik...@home.com> wrote:
<lots of snippage>

>all is good, ja? i guess i'm saying that i can't think of any good reason
>for the standard not to say that definition == prototype.

In your example case, where the prototyped argument list would be (void),
this makes sense. But in other cases, implicitly converting a non-prototype
function definition into a prototype changes the semantics of the program.
E.g.
----------------------------------------
file foo.c:

void foo(a, b, c)
int a; short b; char c;
{
/* whatever */
}

void bar() { foo(1, 16000, '\n'); }

file baz.c:
extern void foo();
void baz() { foo(1, 16000, '\n'); }
----------------------------------------

Under the current rules, the two calls to foo() are equivalent:
the 16000 and '\n' both get promoted to int in the call. If a visible
function definition were taken to be a prototype, then the call in bar()
could pass the arguments differently, making the two function calls
incompatible with each other.

--
Morris M. Keesan -- mke...@kenan.com
Kenan Systems Corp., a wholly-owned subsidiary of Lucent Technologies

0 new messages