Pointer to function in K&R C

N

nathan

Hey there!

I write C based software that I try to keep as portable as possible.
Therefore I support both K&R and ANSI headers. In one of these
headers, there is a pointer to a function with arguments. In ANSI
that's easy, but how about K&R C? Is it:

int foo (int (*bar) ()) {}

or

int foo (int (*bar) (x, y)) {}

or:

int foo (int (*bar) (int, int)) {}

or (unlikely):

int foo (int (*bar) (int x, int y)) {}

Tnx!!
 
H

Harald van Dijk

I write C based software that I try to keep as portable as possible.
Therefore I support both K&R and ANSI headers.

Are there actually any compilers that are of interest to you, that do
not support function prototypes? Prototypes have been standard C for
more than 20 years.
In one of these
headers, there is a pointer to a function with arguments. In ANSI
that's easy, but how about K&R C? Is it:

K&R C does not have "function with argument" types. It has function
types.

In your header:

int foo ();

In your source file:

int foo (bar, x, y)
int (*bar) ();
int x;
int y;
{
return (*bar) (x, y);
}

Keep in mind that K&R C is not a actual standard, and pre-ANSI
compilers vary in behaviour in different aspects.
 
J

Jorgen Grahn

.
Of course any undefined behaviour in your program could lead to your
code being transported 30 years back in time, where K&R compatibility
could then come useful.

That's why I include this in every program I write:

if(time(0)<1e9) {
FILE* f = popen("/bin/mail (e-mail address removed)", "w");
fputs(stock_market_of_1992, f);
fclose(f);
}

I'm not rich yet. I guess that means all my programs work.

/Jorgen
 
K

Keith Thompson

Jorgen Grahn said:
That's why I include this in every program I write:

if(time(0)<1e9) {
FILE* f = popen("/bin/mail (e-mail address removed)", "w");
fputs(stock_market_of_1992, f);
fclose(f);
}

I'm not rich yet. I guess that means all my programs work.

You're not rich because you're sending 1992 stock market information
back to 2001. ((time_t)1e9 is Sun 2001-09-09 01:46:40 UTC, assuming
Unix-style time_t).
 
N

nathan

Are there actually any compilers that are of interest to you, that do
not support function prototypes? Prototypes have been standard C for
more than 20 years.


K&R C does not have "function with argument" types. It has function
types.

In your header:

int foo ();

In your source file:

int foo (bar, x, y)
int (*bar) ();
int x;
int y;
{
return (*bar) (x, y);
}

Keep in mind that K&R C is not a actual standard, and pre-ANSI compilers
vary in behaviour in different aspects.

Hi Harry,
I did some Googling last night and just didn't get the answer so I
mixed thing up:

The question is:

int foo (x, y)
int x;
int y;
{}

int bar (z)
int (*z) ();
{}

is this correct or do we need:

int (*z) (int, int);
int (*z) (x, y);

I hope you catch my drift now. Yes, it's to maintain compatibility
with an old system (Coherent).

Best
Nath
 
C

Chad

Are there actually any compilers that are of interest to you, that do
not support function prototypes? Prototypes have been standard C for
more than 20 years.


K&R C does not have "function with argument" types. It has function
types.

I don't see why the distinction is important.

Chad
 
H

Harald van Dijk

I don't see why the distinction is important.

If K&R C does not have "function with argument" types, then the answer
is "the same way as a pointer to a function without arguments".
 
K

Keith Thompson

Chad said:
I don't see why the distinction is important.

The distinction is that a K&R C function type does not include
information about the function's arguments.
 
K

Keith Thompson

nathan said:
I did some Googling last night and just didn't get the answer so I
mixed thing up:

The question is:

int foo (x, y)
int x;
int y;
{}

int bar (z)
int (*z) ();
{}

That's correct for K&R C.
is this correct or do we need:

int (*z) (int, int);

That's a prototype (a function declaration that includes information
about the types of the arguments), so a pre-ANSI compiler is unlikely
to support it. It's legal in ANSI C or later, but mixing prototypes
and old-style function definitions like that doesn't make much sense.
int (*z) (x, y);

I don't think that's not valid syntax in any version of the language
(unless x and y are type names). (If it is valid, it only tells you how
many parameters the function takes, not their types, and that's not
useful.)
I hope you catch my drift now. Yes, it's to maintain compatibility
with an old system (Coherent).

Does that system not have a C compiler that supports prototypes?
Can you build gcc for it (probably an older version)?

There's an old tool called "ansi2knr" (Google it) that attempts to
convert C code with prototypes into K&R-compatible code without
prototypes. I don't think it was ever 100% functional, but you
might it useful.
 
B

Ben Bacarisse

nathan said:
Hi Harry,
Harry?

I did some Googling last night and just didn't get the answer so I
mixed thing up:

The question is:

int foo (x, y)
int x;
int y;
{}

int bar (z)
int (*z) ();
{}

is this correct

Yes, for K&R C, that's all you need.
or do we need:

int (*z) (int, int);
int (*z) (x, y);

Neither is permitted by the syntax of K&R C.
 
B

Ben Bacarisse

Keith Thompson said:
That's correct for K&R C.


That's a prototype (a function declaration that includes information
about the types of the arguments),

To be picky, this is not a function declaration. It declares an
identifier that denotes an object type rather than a function.

As to whether it is a prototype, on the one hand section 6.2.1 p2
defines a /function prototype/ (in italics) as "a declaration of a
function that declares the types of its parameters". Since this does
not declare a function, it's out. On the other hand, section 6.5.2.2 p2
talks about an expression that denotes a called function (like the 'z'
in 'z(1,2)') as having "a type that includes a prototype". I take that
to mean that the above is not a function prototype but that it declares
an object with a type that includes a prototype.

I don't think that's not valid syntax in any version of the language
(unless x and y are type names).

There's an unintended "not" I think.

<snip>
 
J

James Kuyper

I don't see why the distinction is important.

K&R's function types were completely specified by the return type of the
function. The "function with argument" or prototype declarations that
were added in ANSI C also specified the number and the types of the
arguments (I won't bother trying to describe how functions with a
variable number of arguments complicate the description). Two prototype
declarations are compatible only if the number of arguments match and
the corresponding argument types are compatible.

When you call a function that is declared with a prototype, it's a
constraint violation to pass it the wrong number of arguments. Argument
values are assigned to the corresponding parameters, if any such
assignment would not be allowed, it is also a constraint violation. This
means you generally find out at compile time if you call a function with
the wrong number or wrong types of arguments.

For functions declared with K&R syntax, there's nothing to be checked,
and you won't find out that you've made such errors until run-time (and
not necessarily then, either, depending upon precisely how the function
call actually malfunctions).
 
J

Jorgen Grahn

You're not rich because you're sending 1992 stock market information
back to 2001. ((time_t)1e9 is Sun 2001-09-09 01:46:40 UTC, assuming
Unix-style time_t).

Ah, thanks. I actually *did* the math, but messed up on the
requirements. (And late 2001 was probably not the best time to make
money on stocks anyways; the IT bubble burst some months later as I
recall it.)

/Jorgen
 
J

James Kuyper

Ah, thanks. I actually *did* the math, but messed up on the
requirements. (And late 2001 was probably not the best time to make
money on stocks anyways; the IT bubble burst some months later as I
recall it.)

Which would have made it an excellent time to sell short. If you know
what the market's going to do, you can almost always make money off of
your knowledge.
 
T

Tim Rentsch

Ben Bacarisse said:
Keith Thompson said:
That's correct for K&R C.


That's a prototype (a function declaration that includes information
about the types of the arguments),

To be picky, this is not a function declaration. It declares an
identifier that denotes an object type rather than a function.

As to whether it is a prototype, on the one hand section 6.2.1 p2
defines a /function prototype/ (in italics) as "a declaration of a
function that declares the types of its parameters". Since this does
not declare a function, it's out. On the other hand, section 6.5.2.2 p2
talks about an expression that denotes a called function (like the 'z'
in 'z(1,2)') as having "a type that includes a prototype". I take that
to mean that the above is not a function prototype but that it declares
an object with a type that includes a prototype. [snip unrelated]

That's simply bad wording in this definition; presumably what was
meant is 'function declarator'. Clearly the Standard intends the
term 'function prototype' to include things like declarations of
pointer-to-function types, otherwise other passages in the Standard
are nonsensical -- cf. 6.2.1 p4. I agree the wording in 6.2.1p2 is
poorly chosen, but surely the intended meaning is clear.
 

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

Forum statistics

Threads
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top