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

I don't understand typedef example

30 views
Skip to first unread message

André Hänsel

unread,
Mar 17, 2009, 11:56:20 PM3/17/09
to
Hi list,

"The C book", Chapter 8.3 states:

-----
As a word of warning, typedef can only be used to declare the type of
return value from a function, not the overall type of the function.
The overall type includes information about the function's parameters
as well as the type of its return value.

/*
* Using typedef, declare 'func' to have type
* 'function taking two int arguments, returning int'
*/
typedef int func(int, int);

/* ERROR */
func func_name{ /*....*/ }

/* Correct. Returns pointer to a type 'func' */
func *func_name(){ /*....*/ }
-----

This does not make any sense to me. He says that it is not possible to
typedef the function parameters' types and in the next line (the
comment) he says that he declares "func" to be "function taking two
int arguments" using typedef.

Can you explain this to me?

Regards,
André

Han from China

unread,
Mar 18, 2009, 12:48:51 AM3/18/09
to
Andre Hansel wrote:
> -----
> As a word of warning, typedef can only be used to declare the type of
> return value from a function, not the overall type of the function.
> The overall type includes information about the function's parameters
> as well as the type of its return value.

That isn't the best wording.

> /*
> * Using typedef, declare 'func' to have type
> * 'function taking two int arguments, returning int'
> */
> typedef int func(int, int);

The wording isn't referring to the above typedef.

> /* ERROR */
> func func_name{ /*....*/ }
>
> /* Correct. Returns pointer to a type 'func' */
> func *func_name(){ /*....*/ }

It's referring to the above *use* of a typedef identifier, in this
case 'func'.

> -----
>
> This does not make any sense to me. He says that it is not possible to
> typedef the function parameters' types and in the next line (the
> comment) he says that he declares "func" to be "function taking two
> int arguments" using typedef.

Hope the above clarifies.

The constraint in question can be found in 6.9.1{2} of the latest
C99 draft:

The identifier declared in a function definition (which is the
name of the function) shall have a function type, as specified
by the declarator portion of the function definition.

There's a reference to footnote #141:

The intent is that the type category in a function definition
cannot be inherited from a typedef.

That footnote includes some instructive examples.

You should contact the authors, because the statement "As a word of

warning, typedef can only be used to declare the type of return value

from a function, not the overall type of the function" is contradicted
by the following legal function declaration (based on a footnote
example), which uses a typedef identifier to declare the overall type
of a function:

typedef int F(void);

F g;

You'll notice the standard, in both the constraint and the footnote,
emphasizes a function definition, whereas the book you're reading
doesn't.


Yours,
Han from China

--
"Only entropy comes easy." -- Anton Chekhov

Keith Thompson

unread,
Mar 18, 2009, 3:49:41 AM3/18/09
to

You can declare a typedef for a function type, but you can't use such
a typedef to define a function of that type.

But given that func is a typedef for a function type, func* is a
pointer-to-function type. In his "Correct." example, he doesn't
declare func_name as a function of type func; he declares it as a
function that returns a func*.

--
Keith Thompson (The_Other_Keith) k...@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"

Fred

unread,
Mar 18, 2009, 10:52:41 AM3/18/09
to

Consider this:
typedef char * String;

Then:

String myfunc(...);

So myfunc is a function that returns a string (i.e., a char *).

So your func is typedef'd to be a function taking two int
arguments and returning an int.

Then you declare
func func_name(...);

Your intent was probably to try to show that func_name is
a function taking two int arguments and returning an int.

But in reality you have said that func_name is a function
that returns a func - that is, a function that returns
a function that takes two int args and returns an int.

One common use of such a typedef is when passing a
function as an argument. For example,

int func_name( int a, int b ) {...};

int mynewfunc( int x, int y, func proc ) {
/* somewhere this probably has something like this
* to invoke the function passed in:
*/
int n =(*proc)( a, b );

return n;
}

Then you can call mynewfunc:

int d = mynewfunc( 2, 5, func_name );

--
Fred K

Stephen Sprunk

unread,
Mar 18, 2009, 11:23:34 AM3/18/09
to


"func" means a function taking two ints and returning an int. If you write:

func *func_name() { /*....*/ }

what you have is a function taking no arguments and returning a
pointer-to-func.

This:

func func_name { /*....*/ }

is not valid, period, because (a) func_name doesn't have an argument
list, and (b) func_name can't return a function, only a pointer-to-function.

It never occurred to me to try to use a function typedef to declare the
return value and arguments to another function; that's just not the way
the C syntax works. You could hack up something similar using #define
if you really wanted to, but why?

S

--
Stephen Sprunk "Stupid people surround themselves with smart
CCIE #3723 people. Smart people surround themselves with
K5SSS smart people who disagree with them." --Isaac Jaffe

Keith Thompson

unread,
Mar 18, 2009, 12:48:21 PM3/18/09
to

That particular typedef is a bad idea, just because of the name.
A char* is not a string. A char* value can point to (the first
character of) a string. A "string" is defined as "a contiguous
sequence of characters terminated by and including the first null
character"; it is *not* a pointer. Suggested reading: sections 6
and 8 of the comp.lang.c FAQ, <http://www.c-faq.com>.

But apart from the terminology, yes, myfunc returns a char*.

> So your func is typedef'd to be a function taking two int
> arguments and returning an int.

Right.

Functions, like objects, have types. If I define a function:

int foo(int n) { return n; }

then the function foo has a type that can be described as "function
taking an int argument and returning an int result". This type
can be written in C as "int (int)" (the type name is obtained by
taking the declaration and dropping the function's name). It's
important to keep in mind that a function and a function type
are two different things, just as an object (variable) and its
type are two different things.

The purpose of a typedef is to create a new name, an alias, for an
existing type. You can do this for a function type as easily as for
any other type. (Well, almost as easily; the syntax can be a bit
daunting.)

So the declaration:

typedef int func(int, int);

declare "func" as a name (an alias) for the type "function taking
two int arguments returning an int result", or "int(int, int)".

Once you've declared this alias, you can use it almost anywhere you
can use the original type. For example:
func *ptr;
declared ptr as a pointer object that can points to a function of the
appropriate type, and
func *array_of_pointers[42];
declares array_of_pointers as an array of such pointers.

> Then you declare
> func func_name(...);
>
> Your intent was probably to try to show that func_name is
> a function taking two int arguments and returning an int.
>
> But in reality you have said that func_name is a function
> that returns a func - that is, a function that returns
> a function that takes two int args and returns an int.

Which is illegal. You can't legally have a function that returns a
function. You *can* have a function that returns a function pointer.

> One common use of such a typedef is when passing a
> function as an argument. For example,
>
> int func_name( int a, int b ) {...};
>
> int mynewfunc( int x, int y, func proc ) {

Again, this is illegal, since you can't have a parameter of function
type. You can have a parameter of pointer-to-function type, so this
would be legal (and is probably what you meant):

int mynewfunc( int x, int y, func *proc ) {

> /* somewhere this probably has something like this
> * to invoke the function passed in:
> */
> int n =(*proc)( a, b );
>
> return n;
> }
>
> Then you can call mynewfunc:
>
> int d = mynewfunc( 2, 5, func_name );

func_name is a function, so yes, given that mynewfunc takes an
argument of type func*, this call is valid. Any expression of
function type, including a function name, is implicitly converted to a
pointer to the function.

Given that func is a typedef for a function type, you declare
a function of that type:

func foo;

But you can't use it to *define* the same function:

func foo { return 42 }; /* ILLEGAL */

In my opinion, it's clearer *not* to use the typedef in the function
declaration. (It's perfectly ok to use a typedef as *part of* a
function declaration, such as "func *bar(void)".) I prefer to keep a
function's declaration and definition as similar as possible, so I'd
write:

/* declaration: */
int foo(int a, int b);

/* definition: */
int foo(int a, int b) { /* ... */ }

Finally, you can declare a typedef either for the function type itself
or for a pointer to the function type:

typedef int func(int, int);

typedef int *func_ptr(int, int);

There are arguments for both forms. In code that I've seen, the
latter form is more common than the former; I think a lot of C
programmers aren't even aware that you can declare a typedef for
a function type. On the other hand, declaring a typedef for a
pointer type is generally a bad idea; the fact that something is a
pointer is an important part of the information you need to use it,
and hiding that information behind an alias can cause confusion.
On the other other hand, this argument isn't as strong for
pointers to functions as it is for pointers to objects. You should
be familiar with both forms.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>

Ben Bacarisse

unread,
Mar 18, 2009, 2:03:42 PM3/18/09
to
Stephen Sprunk <ste...@sprunk.org> writes:

> André Hänsel wrote:
<snip>


>> typedef int func(int, int);
>>
>> /* ERROR */
>> func func_name{ /*....*/ }
>>
>> /* Correct. Returns pointer to a type 'func' */
>> func *func_name(){ /*....*/ }

<snip>


> This:
>
> func func_name { /*....*/ }
>
> is not valid, period, because (a) func_name doesn't have an argument
> list, and (b) func_name can't return a function, only a
> pointer-to-function.

It is often more trouble than it is worth to say why something is
invalid (since it is wrong, it could mean anything at all) but I think
you go to far with (b). If I had just read about C's type system and
knew nothing else, I would take

func func_name { /*....*/ }

to be a definition of func_name as a function that returns an int.
After all,

func func_name;

declares it as such, so why would C not permit a definition by adding
a block? Yes, your (a) is the key problem -- there is no obvious
argument list, but the implied type is fine.

--
Ben.

Fred

unread,
Mar 18, 2009, 2:14:12 PM3/18/09
to
On Mar 18, 9:48 am, Keith Thompson <ks...@mib.org> wrote:
>     -- Antony Jay and Jonathan Lynn, "Yes Minister"- Hide quoted text -
>
> - Show quoted text -

Oops - I misread the original typedef - thought it was
typdef int (*func)(int, int);

--
Fred K

Old Wolf

unread,
Mar 18, 2009, 9:39:05 PM3/18/09
to
On Mar 19, 7:03 am, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
> <snip>
> >> typedef int func(int, int);
>
> It is often more trouble than it is worth to say why something is
> invalid (since it is wrong, it could mean anything at all) but I think
> you go to far with (b).  If I had just read about C's type system and
> knew nothing else, I would take
>
>  func func_name { /*....*/ }
>
> to be a definition of func_name as a function that returns an int.

What are the names of the parameters? It
would be annoying as a programmer to have
to refer back to the definition of 'func',
to find out how to use a parameter, not to
mention maintenance problems if someone
mucks with the typedef.

I agree that it would be useful to have
some sort of syntax for defining a function
to match an existing typedef, but I can't
really think of any such good syntax to do this.

Old Wolf

unread,
Mar 18, 2009, 9:48:02 PM3/18/09
to
On Mar 18, 4:56 pm, André Hänsel <an...@webkr.de> wrote:
> Hi list,
>
> "The C book", Chapter 8.3 states:
>
> -----
> As a word of warning, typedef can only be used to declare the type of
> return value from a function, not the overall type of the function.
> The overall type includes information about the function's parameters
> as well as the type of its return value.

This paragraph is completely wrong. A
function typedef can include the function's
formal parameter list. In fact the example
you give does exactly that. The following
code is wrong:

typedef int func(int, int);

func f;

int f(void) { return 0; }

Ben Bacarisse

unread,
Mar 18, 2009, 11:52:42 PM3/18/09
to
Old Wolf <old...@inspire.net.nz> writes:

> On Mar 19, 7:03 am, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
>> <snip>
>> >> typedef int func(int, int);
>>
>> It is often more trouble than it is worth to say why something is
>> invalid (since it is wrong, it could mean anything at all) but I think
>> you go to far with (b).  If I had just read about C's type system and
>> knew nothing else, I would take
>>
>>  func func_name { /*....*/ }
>>
>> to be a definition of func_name as a function that returns an int.
>
> What are the names of the parameters?

Yes, that is the main problem. I agreed with that part of the post.

> It
> would be annoying as a programmer to have
> to refer back to the definition of 'func',
> to find out how to use a parameter, not to
> mention maintenance problems if someone
> mucks with the typedef.

Yes. The typedef may have no named parameters, or there may be more
than one typedef with different names (depending on #if for example)
so it would be a nightmare.

> I agree that it would be useful to have
> some sort of syntax for defining a function
> to match an existing typedef, but I can't
> really think of any such good syntax to do this.

One could do:

typedef int functype(int, int);

(functype f)(a, b)
{
return a + b;
}

You could be permitted to repeat the types if you like:

int (functype f)(int a, int b) { ... }

and the compiler would check that they match.

The parentheses group the function types with name and though odd, not
so very odd since C uses ()s for grouping in types already.

--
Ben.

André Hänsel

unread,
Mar 22, 2009, 7:48:05 PM3/22/09
to
Thanks for all your answers. They make it clear. So I understand that
all the author wanted to say is that there is no syntax in C to use a
typedef'd function type to define (or even declare) a function of that
type.

Since the only use of such a typedef is to make a type "pointer to
such a function" I probably will stick to the "typedef int
*pointer_to_such_function(int,int)" syntax in my own code.

pete

unread,
Mar 22, 2009, 8:17:21 PM3/22/09
to

Did you understand the part of the answers
which explained about the author being wrong?

You *can* use a typedef to declare a function.

--
pete

André Hänsel

unread,
Mar 22, 2009, 9:34:57 PM3/22/09
to

Actually I don't think the author is wrong but he expresses the facts
in a very unfortunate way. I think by the sentence "As a word of


warning, typedef can only be used to declare the type of return value

from a function, not the overall type of the function." he means
something like "The typedef'd 'type name' cannot be used to define a
function of this type, it can only be used to define a function
returning a pointer to a funtion of this type."
This is what you meant by "using a typedef to declare a function",
isn't it? Or is there really a way to define a function of this very
type?

Barry Schwarz

unread,
Mar 22, 2009, 10:01:33 PM3/22/09
to

You probably meant
typedef int (*ptr)(int, int);
otherwise the asterisk binds to the int.

--
Remove del for email

luser-ex-troll

unread,
Mar 22, 2009, 10:16:00 PM3/22/09
to
On Mar 18, 10:52 pm, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:

I saw that and got so excited that I copied it straight into an editor
and tried to compile. It doesn't work. But I came up with a use that
does work, declaring a function with a function-pointer arg which is
declared by example.

int b(int a, int b) {
return a - b;
}

typedef typeof(b) functype;

int gen_interface(int foo, functype *fp);

--
lxt

pete

unread,
Mar 22, 2009, 10:37:03 PM3/22/09
to

No.

> Or is there really a way to define a function of this very type?

No.
A typedef can be used to declare a function type.
A typedef can't be used to define a function.
I just posted this code recently:

/* BEGIN new.c */

#include <stdio.h>

#define STRING1 "\n/* BEGIN output new.c */\n"
#define STRING2 "/* END output new.c */"

typedef void *copyfunc(void *s1, const void *s2, size_t n);
/*
** mem_cpy and mem_move
** are functions declared with a copyfunc typedef.
*/
copyfunc mem_cpy;
copyfunc mem_move;

int main(void)
{
char string1[sizeof STRING1];
char string2[sizeof STRING2];

mem_cpy(string1, STRING1, sizeof string1);
mem_move(string2, STRING2, sizeof string2);
puts(string1);
puts(string2);
return 0;
}

void *mem_cpy(void *s1, const void *s2, size_t n)
{
unsigned char *p1 = s1;
const unsigned char *p2 = s2;

while (n-- != 0) {
*p1++ = *p2++;
}
return s1;
}

void *mem_move(void *s1, const void *s2, size_t n)
{
unsigned char *p1 = s1;
const unsigned char *p2 = s2;

p2 += n;
while (p2 != s2 && --p2 != s1) {
;
}
if (p2 != s2) {
p2 = s2;
while (n-- != 0) {
p1[n] = p2[n];
}
} else {
while (n-- != 0) {
*p1++ = *p2++;
}
}
return s1;
}

/* END new.c */

--
pete

Keith Thompson

unread,
Mar 22, 2009, 10:42:15 PM3/22/09
to

The terms "declare" and "define" are not interchangeable. You can use
a typedef to *declare* a function, where the typedef specifies the
type of the function itself. You cannot similarly use a typedef to
*define* a function. (Of course a typedef can be used in the
function's return type or parameter types; it just can't be used for
the type of the function itself.)

For example, this is legal:

#include <stdio.h>

/* func_type is a function type, not a pointer-to-function type */
typedef void func_type(void);

/* A function declaration, not a definition: */
func_type say_hello;

int main(void) {
say_hello();
return 0;
}

/* A function definition: */
void say_hello(void) {
puts("Hello");
}

The function say_hello is of type func_type, but you cannot legally
rewrite the *definition* of say_hello using the type name "func_type".

And as a matter of style, I prefer not to use typedefs for function
declarations either, since I like to keep declarations and definitions
as similar as possible (apart from the lack of a body on the
declaration, of course).

(In the above, I largely ignored the fact that a definition is also a
declaration.)

Keith Thompson

unread,
Mar 22, 2009, 10:43:45 PM3/22/09
to
luser-ex-troll <mij...@yahoo.com> writes:
[snip]

> I saw that and got so excited that I copied it straight into an editor
> and tried to compile. It doesn't work. But I came up with a use that
> does work, declaring a function with a function-pointer arg which is
> declared by example.
>
> int b(int a, int b) {
> return a - b;
> }
>
> typedef typeof(b) functype;
>
> int gen_interface(int foo, functype *fp);

typeof is non-standard; I think it's a gcc extension.

Ben Bacarisse

unread,
Mar 22, 2009, 11:21:22 PM3/22/09
to
luser-ex-troll <mij...@yahoo.com> writes:

> On Mar 18, 10:52 pm, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:

<snip>


>> One could do:
>>
>>   typedef int functype(int, int);
>>
>>   (functype f)(a, b)
>>   {
>>       return a + b;
>>   }
>>
>> You could be permitted to repeat the types if you like:
>>
>>   int (functype f)(int a, int b) { ... }
>>
>> and the compiler would check that they match.
>>
>> The parentheses group the function types with name and though odd, not
>> so very odd since C uses ()s for grouping in types already.
>
> I saw that and got so excited that I copied it straight into an editor
> and tried to compile. It doesn't work.

Yes, I hope it is clear I was talking about what one might do in a
hypothetical language like C...

> But I came up with a use that
> does work, declaring a function with a function-pointer arg which is
> declared by example.
>
> int b(int a, int b) {
> return a - b;
> }
>
> typedef typeof(b) functype;
>
> int gen_interface(int foo, functype *fp);

typeof is (as has been pointed out already) non-standard but if you
think about it, all C typedefs are declared "by example" -- you write
an example declaration:

int b(int a, int b);

and simply replace the name with the name you want for the alias abd
put typedef in front:

typdef int functype(int a, int b);

and now functype works like your typeof example. This is true of all
tyepdefs -- they are example declarations with an extra keyword in
front.

--
Ben.

André Hänsel

unread,
Mar 23, 2009, 8:03:59 PM3/23/09
to

Oh, now I understand. Of course I was aware of the difference between
the declaration and the definition, I simply could not understand why
a language may provide a syntax to declare a function using the
typedef but *not* provide a syntax to *define* the function using it.

André Hänsel

unread,
Mar 23, 2009, 8:10:45 PM3/23/09
to

I think I did, yes.

I copied it from Keith's post:

> Finally, you can declare a typedef either for the function type itself
> or for a pointer to the function type:
>
> typedef int func(int, int);
>
> typedef int *func_ptr(int, int);
>
> There are arguments for both forms. In code that I've seen, the
> latter form is more common than the former;

So I think the parentheses slipped his fingers, too. Or did he mean
something completely different?

Keith Thompson

unread,
Mar 23, 2009, 8:43:23 PM3/23/09
to
André Hänsel <an...@webkr.de> writes:
> On 23 Mrz., 03:01, Barry Schwarz <schwa...@dqel.com> wrote:
[...]

>> You probably meant
>>    typedef int (*ptr)(int, int);
>> otherwise the asterisk binds to the int.
>
> I think I did, yes.
>
> I copied it from Keith's post:
>
>> Finally, you can declare a typedef either for the function type itself
>> or for a pointer to the function type:
>>
>> typedef int func(int, int);
>>
>> typedef int *func_ptr(int, int);
>>
>> There are arguments for both forms. In code that I've seen, the
>> latter form is more common than the former;
>
> So I think the parentheses slipped his fingers, too. Or did he mean
> something completely different?

No, I just goofed.

Keith Thompson

unread,
Mar 23, 2009, 8:45:12 PM3/23/09
to
Keith Thompson <ks...@mib.org> writes:
[...]

> Finally, you can declare a typedef either for the function type itself
> or for a pointer to the function type:
>
> typedef int func(int, int);
>
> typedef int *func_ptr(int, int);
[...]

Correction: the second should be

typedef int (*func_ptr)(int, int);

Thanks to Barry Schwarz for catching the error.

pete

unread,
Mar 23, 2009, 9:12:24 PM3/23/09
to

For any given implementation, all objects of the same type
are the same size and have the same rules for value representation.

The type of a function has nothing
to do with the guts of the function definition.

--
pete

Michael Melanson

unread,
Mar 23, 2009, 9:22:09 PM3/23/09
to
pete <pfi...@mindspring.com> writes:

> The type of a function has nothing
> to do with the guts of the function definition.

Two guys named Curry and Howard might have a few things to say about
that. :)

Specifically, Curry-Howard correspondence says that, for a
sufficiently detailed type system, there's a one-to-one matching between
formulae (i.e, functions) and types.

In C this definitely isn't the case, but I thought I'd be pedantic. :)

Cheers!

Michael Melanson

JosephKK

unread,
Mar 23, 2009, 11:47:00 PM3/23/09
to
On Mon, 23 Mar 2009 17:45:12 -0700, Keith Thompson <ks...@mib.org>
wrote:

>Keith Thompson <ks...@mib.org> writes:
>[...]
>> Finally, you can declare a typedef either for the function type itself
>> or for a pointer to the function type:
>>
>> typedef int func(int, int);
>>
>> typedef int *func_ptr(int, int);
>[...]
>
>Correction: the second should be
>
> typedef int (*func_ptr)(int, int);
>
>Thanks to Barry Schwarz for catching the error.

Now i want to recheck my understanding; func_ptr is a new name to a
pointer to a function, that returns an int and takes two ints for
arguments.

Keith Thompson

unread,
Mar 24, 2009, 12:24:54 AM3/24/09
to

To be precise, func_ptr is a new name for particular
pointer-to-function *type*. That type can be described in C as
"int(*)(int, int)", or in English as "pointer to function with two int
parameters returning int".

JosephKK

unread,
Mar 24, 2009, 1:24:45 AM3/24/09
to
On Sun, 22 Mar 2009 19:42:15 -0700, Keith Thompson <ks...@mib.org>
wrote:

<snip>

>The terms "declare" and "define" are not interchangeable. You can use
>a typedef to *declare* a function, where the typedef specifies the
>type of the function itself. You cannot similarly use a typedef to
>*define* a function. (Of course a typedef can be used in the
>function's return type or parameter types; it just can't be used for
>the type of the function itself.)
>

<snip>

I find the word pair "declare" and "implement" much harder to confuse.
Clarity is consistently valuable.
.

pete

unread,
Mar 24, 2009, 3:13:33 AM3/24/09
to

"declaration" and "definition"
are techincal terms described in the C standard.

--
pete

Richard Heathfield

unread,
Mar 24, 2009, 3:29:06 AM3/24/09
to
JosephKK said:

<snip>

> I find the word pair "declare" and "implement" much harder to
> confuse. Clarity is consistently valuable.

In broad terms, "declare" means "make a promise to the compiler that
an object or function exists and is of the given type". If you get
the syntax right, the compiler will believe you, whether or not you
are telling the truth, and will proceed on that assumption. (If the
object or function does not exist, it should be discovered during
linking - but E&OE it will not be found out during compilation.)

In equally broad terms, "define" means "create an object or function
of the given type". (It can also mean "create a type like THIS",
but that's by the by for now.) The compiler is (required by the
Standard to be) bright enough to treat object definitions and
function definitions as declarations (that is, the definition of an
object or function is effectively a guarantee that that object or
function exists!) - so all definitions of objects or functions are
also declarations. The reverse is not true - not all declarations
are definitions.

If you think of what "declare" means in the real world, it helps -
"I declare that I will bring income tax down next year" is a
promise, an announcement, a claim. And so are:

extern int foo;

and

int bar(void);

And, just like the promise to bring down income tax, those claims
may not reflect reality. Definitions, however, change reality by
introducing new objects or functions (or, he added in a futile
attempt at completeness, types). Definitions are concrete.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999

Richard Bos

unread,
Mar 24, 2009, 1:42:21 PM3/24/09
to
Michael Melanson <mic...@michaelmelanson.net> wrote:

For one thing, if it were the case in C, it would make qsort() an
interesting proposition.

Richard

pete

unread,
Mar 24, 2009, 9:20:19 PM3/24/09
to

Also, there's a lot of library functions which have the same type,
but do different things.

double sqrt(double x);
double log(double x);
double log10(double x);
double exp(double x);
double cos(double x);

int isspace(int c);
int isupper(int c);
int islower(int c);
int isalpha(int c);
int isalnum(int c);
int toupper(int c);
int tolower(int c);

--
pete

nick_keigh...@hotmail.com

unread,
Mar 25, 2009, 4:39:43 AM3/25/09
to
On 24 Mar, 07:29, Richard Heathfield <r...@see.sig.invalid> wrote:
> JosephKK said:

> > I find the word pair "declare" and "implement" much harder to
> > confuse. Clarity is consistently valuable.
>
> In broad terms, "declare" means "make a promise to the compiler that
> an object or function exists and is of the given type". If you get
> the syntax right, the compiler will believe you, whether or not you
> are telling the truth, and will proceed on that assumption. (If the
> object or function does not exist, it should be discovered during
> linking - but E&OE it will not be found out during compilation.)
>
> In equally broad terms, "define" means "create an object or function
> of the given type". (It can also mean "create a type like THIS",
> but that's by the by for now.) The compiler is (required by the
> Standard to be) bright enough to treat object definitions and
> function definitions as declarations (that is, the definition of an
> object or function is effectively a guarantee that that object or
> function exists!) - so all definitions of objects or functions are
> also declarations. The reverse is not true - not all declarations
> are definitions.
>
> If you think of what "declare" means in the real world, it helps -
> "I declare that I will bring income tax down next year" is a
> promise, an announcement, a claim. And so are:

ah, but this interpretation of the "real world" hasn't always held.
For instance section 5 of the "Revised Report on the Algorithmic
Language Algol 60" has this to say:

"Declarations serve to define certain properties of the quantities
used in the program, and to associate them with identifiers. A
declaration of an identifier is valid for one block. Outside this
block the particular identifier may be used for other purposes."

In other words what C calls definitions Algol 60 calls declarations.
Gave me trouble for years

Richard Heathfield

unread,
Mar 25, 2009, 4:42:09 AM3/25/09
to
nick_keigh...@hotmail.com said:

<snip>



> In other words what C calls definitions Algol 60 calls
> declarations.

I am not responsible for Algol 60 being broken.

(Of course I'm not responsible for C being non-broken either, but
never mind that!)

nick_keigh...@hotmail.com

unread,
Mar 25, 2009, 8:50:51 AM3/25/09
to
On 25 Mar, 08:42, Richard Heathfield <r...@see.sig.invalid> wrote:
> nick_keighley_nos...@hotmail.com said:

> > In other words what C calls definitions Algol 60 calls
> > declarations.
>
> I am not responsible for Algol 60 being broken.
>
> (Of course I'm not responsible for C being non-broken either, but
> never mind that!)

by this definition Pascal, CORAL and Ada are also borken :-)
(though it could be argued they're all Algol with a different colour
scheme)

Richard Heathfield

unread,
Mar 25, 2009, 10:26:35 AM3/25/09
to
nick_keigh...@hotmail.com said:

> On 25 Mar, 08:42, Richard Heathfield <r...@see.sig.invalid> wrote:
>> nick_keighley_nos...@hotmail.com said:
>
>> > In other words what C calls definitions Algol 60 calls
>> > declarations.
>>
>> I am not responsible for Algol 60 being broken.
>>
>> (Of course I'm not responsible for C being non-broken either, but
>> never mind that!)
>
> by this definition Pascal, CORAL and Ada are also borken :-)

My statement wasn't a definition - it was a declaration! :-)

Richard Bos

unread,
Mar 28, 2009, 1:54:29 PM3/28/09
to
pete <pfi...@mindspring.com> wrote:

> Richard Bos wrote:
> > Michael Melanson <mic...@michaelmelanson.net> wrote:
> >
> >> pete <pfi...@mindspring.com> writes:
> >>
> >>> The type of a function has nothing
> >>> to do with the guts of the function definition.
> >> Two guys named Curry and Howard might have a few things to say about
> >> that. :)
> >>
> >> Specifically, Curry-Howard correspondence says that, for a
> >> sufficiently detailed type system, there's a one-to-one matching between
> >> formulae (i.e, functions) and types.
> >>
> >> In C this definitely isn't the case, but I thought I'd be pedantic. :)
> >
> > For one thing, if it were the case in C, it would make qsort() an
> > interesting proposition.
>
> Also, there's a lot of library functions which have the same type,
> but do different things.

True, but those would, in that hypothetical C-H C, simply have different
types. One would have a type of "function taking an int, doing this with
it, and returning an int"; the other of "function taking an int, doing
_that_ with it, and returning an int". Both could receive the same int,
and the result, still being an int, could be assigned to the same int.

The problem with qsort() is that there would be no straightforward way
of declaring its fourth parameter. There would be no way to state that
qsort() takes "pointer to function taking two void *s, and returning
int". It would have to be "pointer to function taking two void *s,
comparing what they point at in exactly this way and no other, and
returning an int". You could not use the same qsort() to sort both an
array of ints and an array of strings. This would make having a Standard
qsort() function pointless.

Richard

David Thompson

unread,
Mar 30, 2009, 5:36:29 AM3/30/09
to
On Wed, 18 Mar 2009 09:48:21 -0700, Keith Thompson <ks...@mib.org>
wrote:
> Fred <fred.l.kl...@boeing.com> writes:
<snip: typedef for function type>
> > Then you declare
> > func func_name(...);
> >
> > Your intent was probably to try to show that func_name is
> > a function taking two int arguments and returning an int.
> >
> > But in reality you have said that func_name is a function
> > that returns a func - that is, a function that returns
> > a function that takes two int args and returns an int.
>
> Which is illegal. You can't legally have a function that returns a
> function. You *can* have a function that returns a function pointer.
>
Yes.

> > One common use of such a typedef is when passing a
> > function as an argument. For example,
> >
> > int func_name( int a, int b ) {...};
> >
> > int mynewfunc( int x, int y, func proc ) {
>
> Again, this is illegal, since you can't have a parameter of function
> type. You can have a parameter of pointer-to-function type, so this
> would be legal (and is probably what you meant):
>
No. You can't actually have a function parameter, but if you write a
parameter with a function type F, it is 'adjusted' to F*, in the same
way as the much more common and familiar case that an array type T[]
is adjusted to T* . 6.7.5.3p8 previously misplaced in 6.7.1.

In both cases, many people feel it is _clearer_ to explicitly write
the pointer type, but it is perfectly legal to do the others.

<snip>
> Given that func is a typedef for a function type, you declare
> a function of that type:
>
> func foo;
>
s/you/you can/

> But you can't use it to *define* the same function:
>
> func foo { return 42 }; /* ILLEGAL */
>
Yes.

> In my opinion, it's clearer *not* to use the typedef in the function
> declaration. (It's perfectly ok to use a typedef as *part of* a
> function declaration, such as "func *bar(void)".) I prefer to keep a
> function's declaration and definition as similar as possible, ...

I agree (both result and reason).

Han from China

unread,
Mar 30, 2009, 7:57:31 AM3/30/09
to
David Thompson wrote:

> Keith Thompson wrote:
>> Given that func is a typedef for a function type, you declare
>> a function of that type:
>>
>> func foo;
>
> s/you/you can/

Errr... is this a case of one Thompson trying to out-Thompson
the other Thompson? :-) I'm failing to see what that change adds
to Keith's comment that wasn't already clearly implicit in it.


Yours,
Han from China

--
"Only entropy comes easy." -- Anton Chekhov

Kenny McCormack

unread,
Mar 30, 2009, 8:20:42 AM3/30/09
to
In article <e141ab1e7e774437...@pseudo.borked.net>,

Han from China <autistic...@comp.lang.c> wrote:
>David Thompson wrote:
>> Keith Thompson wrote:
>>> Given that func is a typedef for a function type, you declare
>>> a function of that type:
>>>
>>> func foo;
>>
>> s/you/you can/
>
>Errr... is this a case of one Thompson trying to out-Thompson
>the other Thompson? :-) I'm failing to see what that change adds
>to Keith's comment that wasn't already clearly implicit in it.

To be fair, I think that this was just a case of over-exuberance.

But to understand that comment, we must first examine the real,
underlying question - which is: Do newbies benefit from having these
"human compilers" go over their code line-by-line? And, the closely
related question: Do they appreciate it?

Obviously, the "human compilers" (The Thompson Twins, the Ambuhls, the
MacIntires) assume the answers to these questions are (unqualified) yes(s).
Equally clearly, sensible people aren't so sure, and some, including
this author, think the correct answer is in the negative.

Given the above, I'm sure Human Compiler David Thompson saw the above as
simply another syntax error, emitted the required diagnostic, and
moved on to the next, without giving the matter a second thought.

As I say, in that context, really just a case of over-exuberance.

Keith Thompson

unread,
Mar 30, 2009, 11:40:29 AM3/30/09
to
David Thompson <dave.th...@verizon.net> writes:
> On Wed, 18 Mar 2009 09:48:21 -0700, Keith Thompson <ks...@mib.org>
> wrote:
>> Fred <fred.l.kl...@boeing.com> writes:
> <snip: typedef for function type>
[...]

>> > One common use of such a typedef is when passing a
>> > function as an argument. For example,
>> >
>> > int func_name( int a, int b ) {...};
>> >
>> > int mynewfunc( int x, int y, func proc ) {
>>
>> Again, this is illegal, since you can't have a parameter of function
>> type. You can have a parameter of pointer-to-function type, so this
>> would be legal (and is probably what you meant):
>>
> No. You can't actually have a function parameter, but if you write a
> parameter with a function type F, it is 'adjusted' to F*, in the same
> way as the much more common and familiar case that an array type T[]
> is adjusted to T* . 6.7.5.3p8 previously misplaced in 6.7.1.

You're right, thanks for the correction.

> In both cases, many people feel it is _clearer_ to explicitly write
> the pointer type,

I do -- not least because a lot of C programmers don't know about the
rule.

> but it is perfectly legal to do the others.

[...]

0 new messages