By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
434,998 Members | 2,773 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 434,998 IT Pros & Developers. It's quick & easy.

Warning with K&R style function definition

P: n/a
I have some code that has in the header file:

void foo( char bar );

and in the source file:
void foo( bar )
char bar;
{ /* etc. */ }

The compiler (with many warnings enabled) warns that the
prototype doesn't match the definition. (However this code
has worked fine in the past, I only turned the warning level
up recently and the warning appeared).

Given that the prototype is visible in the source file, is
there actually any problem with this code? The compiler
can see the prototype when it is compiling the definition
so must it know to grab a char off the stack (or whatever)
instead of an int?

NB. The definition can't be changed to ANSI-style because
it's automatically generated by a third party precompiler.

Jun 14 '07 #1
Share this Question
Share on Google+
13 Replies


P: n/a
Old Wolf wrote:
I have some code that has in the header file:

void foo( char bar );

and in the source file:
void foo( bar )
char bar;
{ /* etc. */ }

The compiler (with many warnings enabled) warns that the
prototype doesn't match the definition. (However this code
has worked fine in the past, I only turned the warning level
up recently and the warning appeared).

Given that the prototype is visible in the source file, is
there actually any problem with this code? The compiler
can see the prototype when it is compiling the definition
so must it know to grab a char off the stack (or whatever)
instead of an int?
Your declaration says that the caller passes an argument of type char. Your
definition says that the caller passes an argument of type int[*], which
foo() will convert to a char when the function is called. The compiler is
right to complain.
NB. The definition can't be changed to ANSI-style because
it's automatically generated by a third party precompiler.
In your header, you can use

void foo( int bar );

and in your source file, you can either use

void foo( bar )
int bar;
{
char baz = bar;
/* ... */
}

or if your precompiler can handle it, you can change the header as shown
above, but keep the source file as

void foo( bar )
char bar;
{
/* ... */
}
[*] assuming CHAR_MAX <= INT_MAX
Jun 14 '07 #2

P: n/a
On Jun 14, 12:25 pm, Harald van D k <true...@gmail.comwrote:
Old Wolf wrote:
I have some code that has in the header file:
void foo( char bar );
and in the source file:
void foo( bar )
char bar;
{ /* etc. */ }

Your declaration says that the caller passes an argument of type char. Your
definition says that the caller passes an argument of type int[*], which
foo() will convert to a char when the function is called. The compiler is
right to complain.
So the compiler will read the arguments as per K&R,
and not as per the visible prototype?
NB. The definition can't be changed to ANSI-style because
it's automatically generated by a third party precompiler.

In your header, you can use

void foo( int bar );

and in your source file, you can either use

void foo( bar )
int bar;
{
char baz = bar;
That was my temporary workaround :)
or if your precompiler can handle it, you can change the header as shown
above, but keep the source file as

void foo( bar )
char bar;
{
I'll give that a go and see if it likes it.
How is the conversion from int to char specified
for these K&R style definitions? Does it read an
int and then convert in the same way as an
ordinary implicit conversion from int to char?

Jun 14 '07 #3

P: n/a
On Jun 14, 7:57 am, Old Wolf <oldw...@inspire.net.nzwrote:
I have some code that has in the header file:

void foo( char bar );
This is a ANSI C style declare.
Jun 14 '07 #4

P: n/a
Old Wolf wrote:
On Jun 14, 12:25 pm, Harald van D k <true...@gmail.comwrote:
>Old Wolf wrote:
>>I have some code that has in the header file:
void foo( char bar );
and in the source file:
void foo( bar )
char bar;
{ /* etc. */ }
Your declaration says that the caller passes an argument of type char. Your
definition says that the caller passes an argument of type int[*], which
foo() will convert to a char when the function is called. The compiler is
right to complain.

So the compiler will read the arguments as per K&R,
and not as per the visible prototype?
The header's declaration conflicts with the function's
definition (which is also a declaration). If the header said

void floo(double boo);

.... and the definition said

int floo(int goo, char *shoo, const struct glue **moo)
{ ... }

.... would you expect the compiler to reconcile them in
some magical way? Of course not: The declaration and the
definition disagree, and that's that. The compiler must
issue a diagnostic; if it then decides to accept the faulty
program, it "reads arguments" according to its own whim.

--
Eric Sosman
es*****@acm-dot-org.invalid
Jun 14 '07 #5

P: n/a
Eric Sosman <esos...@acm-dot-org.invalidwrote:
The header's declaration conflicts with the function's
definition (which is also a declaration). If the header said

void floo(double boo);

... and the definition said

int floo(int goo, char *shoo, const struct glue **moo)
{ ... }

... would you expect the compiler to reconcile them in
some magical way? Of course not: The declaration and the
definition disagree, and that's that.
If, as suggested by Harald, the header is:
void foo( int bar );

and the definition is:
void foo( bar )
char bar;
{ .... }

then do you know if the code is correct, or is this
still a mismatch? I'm concerned about how the compiler
will turn the int 'bar' into a char.

Jun 14 '07 #6

P: n/a
Old Wolf wrote:
Eric Sosman <esos...@acm-dot-org.invalidwrote:
> The header's declaration conflicts with the function's
definition (which is also a declaration). If the header said

void floo(double boo);

... and the definition said

int floo(int goo, char *shoo, const struct glue **moo)
{ ... }

... would you expect the compiler to reconcile them in
some magical way? Of course not: The declaration and the
definition disagree, and that's that.

If, as suggested by Harald, the header is:
void foo( int bar );

and the definition is:
void foo( bar )
char bar;
{ .... }

then do you know if the code is correct, or is this
still a mismatch? I'm concerned about how the compiler
will turn the int 'bar' into a char.
Wouldn't that be UB? The compiler might use different tricks
(registers?) to pass int and char to functions.

--
Ian Collins.
Jun 14 '07 #7

P: n/a
On Jun 14, 3:26 pm, Ian Collins <ian-n...@hotmail.comwrote:
Old Wolf wrote:
If, as suggested by Harald, the header is:
void foo( int bar );
and the definition is:
void foo( bar )
char bar;
{ .... }
then do you know if the code is correct, or is this
still a mismatch? I'm concerned about how the compiler
will turn the int 'bar' into a char.

Wouldn't that be UB? The compiler might use different tricks
(registers?) to pass int and char to functions.
Well it might be OK if the behaviour of the
definition is to read an int using the int-passing
mechanism, and then convert it to char using an
implicit conversion. That's what Harald suggested.
I don't know whether the compiler will behave this
way or not; I was wondering if Eric could confirm
or deny.

Jun 14 '07 #8

P: n/a
Old Wolf wrote:
On Jun 14, 3:26 pm, Ian Collins <ian-n...@hotmail.comwrote:
>Old Wolf wrote:
>>If, as suggested by Harald, the header is:
void foo( int bar );
and the definition is:
void foo( bar )
char bar;
{ .... }
then do you know if the code is correct, or is this
still a mismatch? I'm concerned about how the compiler
will turn the int 'bar' into a char.
Wouldn't that be UB? The compiler might use different tricks
(registers?) to pass int and char to functions.

Well it might be OK if the behaviour of the
definition is to read an int using the int-passing
mechanism, and then convert it to char using an
implicit conversion. That's what Harald suggested.
I'd expect the char you pass to be sign extended to int (assuming char
is signed) and passed by whatever means to the function. How the
parameter value is retrieved would determine whether this would work.

--
Ian Collins.
Jun 14 '07 #9

P: n/a
Old Wolf wrote:
On Jun 14, 12:25 pm, Harald van D k <true...@gmail.comwrote:
>Old Wolf wrote:
I have some code that has in the header file:
void foo( char bar );
and in the source file:
void foo( bar )
char bar;
{ /* etc. */ }

Your declaration says that the caller passes an argument of type char.
Your definition says that the caller passes an argument of type int[*],
which foo() will convert to a char when the function is called. The
compiler is right to complain.

So the compiler will read the arguments as per K&R,
and not as per the visible prototype?
Yes.
NB. The definition can't be changed to ANSI-style because
it's automatically generated by a third party precompiler.

In your header, you can use

void foo( int bar );

and in your source file, you can either use

void foo( bar )
int bar;
{
char baz = bar;

That was my temporary workaround :)
>or if your precompiler can handle it, you can change the header as shown
above, but keep the source file as

void foo( bar )
char bar;
{

I'll give that a go and see if it likes it.
How is the conversion from int to char specified
for these K&R style definitions? Does it read an
int and then convert in the same way as an
ordinary implicit conversion from int to char?
Right. The function call operator will have converted foo's argument to int,
and that argument is then converted "as if by assignment" to char on entry
of foo.
Jun 14 '07 #10

P: n/a
On Wed, 13 Jun 2007 16:57:14 -0700, in comp.lang.c , Old Wolf
<ol*****@inspire.net.nzwrote:
>I have some code that has in the header file:

void foo( char bar );

and in the source file:
void foo( bar )
char bar;
{ /* etc. */ }

The compiler (with many warnings enabled) warns that the
prototype doesn't match the definition. (However this code
has worked fine in the past, I only turned the warning level
up recently and the warning appeared).
Fixes are either convert the definition to ANSI style, or remove the
prototype (make it a declaration instead).
>Given that the prototype is visible in the source file, is
there actually any problem with this code?
Quite possibly. The prototype tells the compiler to expect a char, but
the definition suggests otherwise so the compiler can presumably jump
either way.
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Jun 14 '07 #11

P: n/a
Old Wolf wrote:
Eric Sosman <esos...@acm-dot-org.invalidwrote:
> The header's declaration conflicts with the function's
definition (which is also a declaration). If the header said

void floo(double boo);

... and the definition said

int floo(int goo, char *shoo, const struct glue **moo)
{ ... }

... would you expect the compiler to reconcile them in
some magical way? Of course not: The declaration and the
definition disagree, and that's that.

If, as suggested by Harald, the header is:
void foo( int bar );

and the definition is:
void foo( bar )
char bar;
{ .... }

then do you know if the code is correct, or is this
still a mismatch? I'm concerned about how the compiler
will turn the int 'bar' into a char.
It's implementation-defined whether Harald's rewrite
is correct. On systems where plain `char' promotes to
`int' it's correct. On those few where `char' promotes
to `unsigned int' (INT_MAX < CHAR_MAX <= UINT_MAX), the
declaration and definition disagree. Even on most of the
latter you'll get away with it -- but you'll know in your
heart that it's wrong.

"You've got to ask yourself one question: 'Do I
feel lucky?' Well do ya, punk?" -- Harry Callahan

--
Eric Sosman
es*****@acm-dot-org.invalid
Jun 14 '07 #12

P: n/a
Old Wolf wrote:
On Jun 14, 3:26 pm, Ian Collins <ian-n...@hotmail.comwrote:
>>Old Wolf wrote:
>>>If, as suggested by Harald, the header is:
void foo( int bar );
>>>and the definition is:
void foo( bar )
char bar;
{ .... }
>>>then do you know if the code is correct, or is this
still a mismatch? I'm concerned about how the compiler
will turn the int 'bar' into a char.

Wouldn't that be UB? The compiler might use different tricks
(registers?) to pass int and char to functions.

Well it might be OK if the behaviour of the
definition is to read an int using the int-passing
mechanism, and then convert it to char using an
implicit conversion. That's what Harald suggested.
I don't know whether the compiler will behave this
way or not; I was wondering if Eric could confirm
or deny.
That depends on the particular compiler. If you are only using a single
compiler, you can verify. If it were me, I would change the code to
make it Standard conforming.

--
Thad
Jun 14 '07 #13

P: n/a
On Jun 14, 4:57 am, Old Wolf <oldw...@inspire.net.nzwrote:
I have some code that has in the header file:

void foo( char bar );
Changing this to

#include <limits.h>

#if CHAR_MAX <= INT_MAX
void foo(int);
#else
void foo(unsigned int);
#endif

I think this will solve the problem cited by Eric.
>
and in the source file:
void foo( bar )
char bar;
{ /* etc. */ }
In K&R style of function definition, the functions definition like the
above are effectively equivalent to:

void foo( buf_bar )
PROMOTED_TYPE buf_bar;/*PROMOTED_TYPE is int if CHAR_MAX <= INT_MAX or
else it is unsigned int*/
{
char bar = buf_bar;
/*Use 'bar' as char in ur code*/
/* etc. */
}

This ratiociantes the error generated by the compiler.
>
The compiler (with many warnings enabled) warns that the
prototype doesn't match the definition. (However this code
has worked fine in the past, I only turned the warning level
up recently and the warning appeared).

Given that the prototype is visible in the source file, is
there actually any problem with this code? The compiler
can see the prototype when it is compiling the definition
so must it know to grab a char off the stack (or whatever)
instead of an int?

NB. The definition can't be changed to ANSI-style because
it's automatically generated by a third party precompiler.

Jun 14 '07 #14

This discussion thread is closed

Replies have been disabled for this discussion.