473,379 Members | 1,533 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,379 software developers and data experts.

Warning with K&R style function definition

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
13 3011
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
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
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
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
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
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
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
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
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
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
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
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
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

28
by: Michael B. | last post by:
I tend to use rather descriptive names for parameters, so the old style of declaration appeals to me, as I can keep a declaration within 80 chars: void * newKlElem...
44
by: Agoston Bejo | last post by:
What happens exactly when I do the following: struct A { int i; string j; A() {} }; void f(A& a) { cout << a.i << endl;
2
by: Alex | last post by:
Hi all, I'm writing a small web application which searches a database based on a date field, and populates a datagrid control with the results. The datagrid control has selection buttons added...
17
by: I.M. !Knuth | last post by:
Hi. I'm more-or-less a C newbie. I thought I had pointers under control until I started goofing around with this: ...
92
by: Heinrich Pumpernickel | last post by:
what does this warning mean ? #include <stdio.h> int main() { long l = 100; printf("l is %li\n", l * 10L);
1
by: dewi | last post by:
Dear All, I am trying to compile a C code using Visual C++. Can anyone explain how to solve it? Thank You. #include <math.h> #include <string.h> #include "RV2AJFRONT_NEW.h" #include...
8
by: benn | last post by:
Here's the setup... Defines.h file contains: enum DAY { monday, tueday }; DayFunctions.h contains prototype: void printIsMonday ( enum DAY currentDay); DayFunctions.c contains:
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.