mark@drd.UUCP (Mark Lawrence) (11/12/88)
I compile the following code fragment:
--
#include <stdio.h>
char *rpeet ( short, char );
char rpeet_temp[81];
char *rpeet ( num, ch )
short num;
char ch;
{
int i;
memset( rpeet_temp, ch, num );
rpeet_temp[num] = '\0';
return( rpeet_temp );
}
--
and get the following gripe from my compiler (gcc 1.30):
rpeet.c: In function rpeet:
rpeet.c:9: argument `num' doesn't match function prototype
rpeet.c:9: argument `ch' doesn't match function prototype
Am I doing something wrong here or is the compiler just grumpy today?
(Please respond by e-mail. I don't normally read this group).
Mark
tulsun!drd!mark@Sun.COM
DRD Corporation mlawrence@jarsun1.ZONE1.COM
(918)743-3013 drd!mark@apctrc.UU.NET
okstate!romed!drd!mark@rutgers.EDU
seanf@sco.COM (Sean Fagan) (11/14/88)
In article <310@drd.UUCP> mark@drd.UUCP () writes: [about the gcc problem with:] >char *rpeet ( short, char ); >char *rpeet ( num, ch ) > short num; > char ch; [where gcc will complain about num beind redeclared as an int] gcc is behaving as if you had done a new-style declaration (since you can have the 'int' as optional, you can declare 'int main(ac, char **av)'), but had also predeclared it with a prototype. I personally think that gcc is wrong in this respect, but haven't had enough time lately to fix it. The problem is that gcc "does not have infinite lookahead." Stallman maintains that ANSI says to expand the arguments to match the prototype, and you are declaring rpeet (in the second one) as having to arguments of type int. I, however, maintain what what ANSI says is that, if you declare a function using old-style declaration (as you did), then you do not expand the arguments unless a prototype is given; but if you use newstyle declarations (char *rpeet ( short num, char ch) {), everything is as if you had also given a prototype. Does anybody who knows the ANSI draft agree with me (Chris? Dough? Dennis?). BTW, K&Rr2 warns about mixing old-style and new-style declarations; it seems to be a good idea 8-). -- Sean Eric Fagan | "Engineering without management is *ART*" seanf@sco.UUCP | Jeff Johnson (jeffj@sco) (408) 458-1422 | Any opinions expressed are my own, not my employers'.
Don_A_Corbitt@cup.portal.com (11/14/88)
>char *rpeet ( short, char ); >char *rpeet ( num, ch) > short num; char ch; >-- >and get the following gripe from my compiler (gcc 1.30): > >rpeet.c: In function rpeet: >rpeekkjt.c:9: argument `num' doesn't match function prototype >rpeet.c:9: argument `ch' doesn't match function prototype > >Mark > tulsun!drd!mark@Sun.COM > DRD Corporation mlawrence@jarsun1.ZONE1.COM > (918)743-3013 drd!mark@apctrc.UU.NET > okstate!romed!drd!mark@rutgers.EDU The problem is you are mixing declaration types. Old style (K&R) automatically promotes short/char to int. New style (ANSI) lets you declare/pass shorts and chars (although it is usually less efficient). You should declare rpeet as char *rpeet(short num, char ch) { ... Don Corbitt, CrystalGraphics, Inc. Don_A_Corbitt@cup.portal.com "The place with no .signature file" (This is my first posting, if it ends up in New Zealand and nowhere else, I'd appreciate mailed hints on what I shoulda done...:-)
friedl@vsi.COM (Stephen J. Friedl) (11/15/88)
In article <310@drd.UUCP>, mark@drd.UUCP (Mark Lawrence) writes: > I compile the following code fragment: > > char *rpeet ( short, char ); /* just a declaration */ > > char *rpeet ( num, ch ) /* actual definition */ > short num; char ch; > { > /* foo */ > > and get the following gripe from my compiler (gcc 1.30): > > rpeet.c:9: argument `num' doesn't match function prototype > rpeet.c:9: argument `ch' doesn't match function prototype This is a gotcha that is not obvious -- it should be of general interest to all using a dpANS compiler. This compiler message is correct. In an old-style function declaration, the *actual* types of the arguments are those that would result from the default argument promotions (char-->int, short-->int, float-->double). So the above is the same as if the user had written: char *foo ( short, char ); vvv------------------- NOTE `int' char *foo ( num, ch ) int num, ch; { /* foo */ which is a mismatch. The solution is to either declare both args to be int everywhere or to use the prototype format for the function definition. The standard says [p 66, May88 dpANS]: 3.5.4.3. Function declarators (including prototypes): [....] If one [function declaration] type has a parameter-list type and the other type is specified by a function definition that contains a (possibly empty) identifier list, both shall agree in the number of parameters, and the type of each prototype parameter shall be compatible with the type that results from the application of the default argument promotions to the type of the corresponding identifier. ---- Followups to comp.std.c Steve, the stumbling lint (Hi Karl!) -- Steve Friedl V-Systems, Inc. +1 714 545 6442 3B2-kind-of-guy friedl@vsi.com {backbones}!vsi.com!friedl attmail!vsi!friedl ------------Nancy Reagan on the worm: "Just say OH NO!"------------
gwyn@smoke.BRL.MIL (Doug Gwyn ) (11/15/88)
In article <1704@scolex> seanf@sco.COM (Sean Fagan) writes: -In article <310@drd.UUCP> mark@drd.UUCP () writes: ->char *rpeet ( short, char ); ->char *rpeet ( num, ch ) -> short num; -> char ch; -I, however, maintain what what ANSI says is that, if you declare a function -using old-style declaration (as you did), then you do not expand the -arguments unless a prototype is given; but if you use newstyle declarations -(char *rpeet ( short num, char ch) {), everything is as if you had also -given a prototype. I don't have the draft Standard at hand right now, but I'm pretty sure Stallman is right to have gcc diagnose this. Old-style function syntax requires widened arguments but the prototype indicates unwidened. This is clearly a type clash. It is possible that the draft Standard really says that a compiler has to straighten things out in cases like this example, but I would find it surprising (and dangerous).
jnh@ece-csc.UUCP (Joseph Nathan Hall) (11/15/88)
In article <8889@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: In article <1704@scolex> seanf@sco.COM (Sean Fagan) writes: -In article <310@drd.UUCP> mark@drd.UUCP () writes: ->char *rpeet ( short, char ); ->char *rpeet ( num, ch ) -> short num; -> char ch; -I, however, maintain what what ANSI says is that, if you declare a function -using old-style declaration (as you did), then you do not expand the -arguments unless a prototype is given; but if you use newstyle declarations -(char *rpeet ( short num, char ch) {), everything is as if you had also -given a prototype. I don't have the draft Standard at hand right now, but I'm pretty sure Stallman is right to have gcc diagnose this. Old-style function syntax requires widened arguments but the prototype indicates unwidened. This is clearly a type clash. It is possible that the draft Standard really says that a compiler has to straighten things out in cases like this example, but I would find it surprising (and dangerous). Not only does VAX (VMS) C diagnose this, it prohibits it. -- v v sssss|| joseph hall || 201-1D Hampton Lee Court v v s s || jnh@ece-csc.ncsu.edu (Internet) || Cary, NC 27511 v sss || the opinions expressed herein are not necessarily those of my -----------|| employer, north carolina state university . . . . . . . . . . .
rkl1@hound.UUCP (K.LAUX) (11/16/88)
In article <310@drd.UUCP>, mark@drd.UUCP (Mark Lawrence) writes: | I compile the following code fragment: | -- | #include <stdio.h> | | char *rpeet ( short, char ); | char rpeet_temp[81]; | | char *rpeet ( num, ch ) | short num; | char ch; | { | int i; | | memset( rpeet_temp, ch, num ); ^^ ^^^ <--***NOTE*** | rpeet_temp[num] = '\0'; | return( rpeet_temp ); | } | -- | and get the following gripe from my compiler (gcc 1.30): | | rpeet.c: In function rpeet: | rpeet.c:9: argument `num' doesn't match function prototype | rpeet.c:9: argument `ch' doesn't match function prototype | I don't think the compiler is complaining at all about the function prototype for rpeet; it's complaining about the call to MEMSET. The function prototype for memset () is: void *memset (void *dest, int c, size_t count); ^^^ ^^^^^^ and neither 'num' nor 'ch' is of the proper type. --rkl
rkl1@hound.UUCP (K.LAUX) (11/16/88)
Everyone seems to have taken up the 'widened/unwidened' debate on function rpeet. Would someone who has access to the gcc compiler please try to compile the fragment with the correct argument types supplied to the MEMSET call (see previous posting) and post the results to the net? 'Cause I think y'all are missing the boat and that the compiler is complaining *only* about the memset call, not the function prototype of rpeet. --rkl
seanf@sco.COM (Sean Fagan) (11/17/88)
In article <8889@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: }In article <1704@scolex> seanf@sco.COM (Sean Fagan) writes: }-In article <310@drd.UUCP> mark@drd.UUCP () writes: }->char *rpeet ( short, char ); }->char *rpeet ( num, ch ) }-> short num; }-> char ch; }-I, however, maintain what what ANSI says is that, if you declare a function }-using old-style declaration (as you did), then you do not expand the }-arguments unless a prototype is given; but if you use newstyle declarations }-(char *rpeet ( short num, char ch) {), everything is as if you had also }-given a prototype. } }I don't have the draft Standard at hand right now, but I'm pretty sure }Stallman is right to have gcc diagnose this. Old-style function syntax }requires widened arguments but the prototype indicates unwidened. This }is clearly a type clash. It is possible that the draft Standard really }says that a compiler has to straighten things out in cases like this }example, but I would find it surprising (and dangerous). Ooops. Just got a nice new copy of the Draft, and you're right: Section 3.5.4.3 (Funciton declarators (including prototypes)), page 66, lines 8-12: If one type has a parameter type list and the other type is specified by a function definition that contains a (possibly empty) identifier list, both shall agree in the number of parameters, and the type of each prototype parameter shall be compatable with the type that results from the application of the default argument promotions to the type of the corresponding identifier. Ok. Something I may have to look in for MSC. I still think that somebody should fix it so that GCC will accept the mixture, unless -ansi, or -pendantic, is specified, but that's just me (or appears to be 8-)). So, the moral of the story: Don't pass in char's, short's, or float's to your subroutines unless you want a Real(tm) ANSI C compiler to choke on it 8-). -- Sean Eric Fagan | "Engineering without management is *ART*" seanf@sco.UUCP | Jeff Johnson (jeffj@sco) (408) 458-1422 | Any opinions expressed are my own, not my employers'.
mark@drd.UUCP (Mark Lawrence) (11/17/88)
In article <310@drd.UUCP>, I wrote:
I compile the following code fragment:
[frag deleted]
rkl1@hound.UUCP (K.LAUX) wrote:
I don't think the compiler is complaining at all about the function
prototype for rpeet; it's complaining about the call to MEMSET.
The function prototype for memset () is:
void *memset (void *dest, int c, size_t count);
What the compiler _should_ gripe about and what it _does_ can, I
suppose, be argued (not by me, however, I'm out of my league).
However, when I declared the argument types in the definition using
new-style, the compiler quit complaining.
gwyn@smoke.BRL.MIL (Doug Gwyn ) (11/18/88)
In article <1736@scolex> seanf@sco.COM (Sean Fagan) writes: >So, the moral of the story: Don't pass in char's, short's, or float's to >your subroutines unless you want a Real(tm) ANSI C compiler to choke on it No, that's the wrong moral. The correct conclusion is that prototypes for old-style-defined functions must declare the parameters with the correctly widened types. In other words, when converting to prototypes either convert EVERY reference to a function AND its definition to use compatible prototypes (in which case any appropriate argument type can be declared), or else use only widened parameter types. For example, extern double sin(float); is wrong because for reasons of compatibility the parameter must be of type double by the time it reaches the innards of the function.
mac3n@babbage.acc.virginia.edu (Alex Colvin) (11/19/88)
In article <8916@smoke.BRL.MIL>, gwyn@smoke.BRL.MIL (Doug Gwyn ) writes: > In article <1736@scolex> seanf@sco.COM (Sean Fagan) writes: > >So, the moral of the story: Don't pass in char's, short's, or float's to > >your subroutines unless you want a Real(tm) ANSI C compiler to choke on it > > No, that's the wrong moral. The correct conclusion is that prototypes > for old-style-defined functions must declare the parameters with the > correctly widened types. It's true. Be careful declaring a (float) parameter in K&R C. What happens when you pass its address to something that expects (float *)? Most stuff works OK when you're on a little-end address machine where the beginning of (int) looks like (char). Less common is where the beginning of (double) looks like a (float). Kids, don't try this on your big-end or word addressed machines at home. You'll get the wrong (char). I understand that ANSI C may be an annoyance to those of you with VAXes, but I can't afford one and it sure helps me.
seanf@sco.COM (Sean Fagan) (11/20/88)
In article <412@babbage.acc.virginia.edu> mac3n@babbage.acc.virginia.edu (Alex Colvin) writes: >In article <8916@smoke.BRL.MIL>, gwyn@smoke.BRL.MIL (Doug Gwyn ) writes: >> In article <1736@scolex> seanf@sco.COM (Sean Fagan) writes: >> >So, the moral of the story: Don't pass in char's, short's, or float's to >> >your subroutines unless you want a Real(tm) ANSI C compiler to choke on it [both Doug and Alex complain] *arggh*! I forgot the blasted '8-)'! I *like* ANSI C! I also *like* passing in char, short, or floats, when it will make my meaning clearer! However, I also prefer declaring parameters the old-style way, since it can save me typing. I want the best of both worlds! Surely this isn't too much to ask for? 8-; Again, I think most ANSI-C compilers will support this as an option, and I *still* think GNU C should (just wait until I can get some free time...!). -- Sean Eric Fagan | "Engineering without management is *ART*" seanf@sco.UUCP | Jeff Johnson (jeffj@sco) (408) 458-1422 | Any opinions expressed are my own, not my employers'.
gwyn@smoke.BRL.MIL (Doug Gwyn ) (11/22/88)
In article <1763@scolex> seanf@sco.COM (Sean Fagan) writes: >However, I also prefer declaring parameters the old-style way, ... >Again, I think most ANSI-C compilers will support this as an option, ... It's not an option; ANSI C requires that old-style declarations and definitions also be supported. It is the attempt to mix both styles for the same function that causes potential problems.