rlkd@opusys.UUCP (R.L.K.Dattatri) (08/24/89)
Here is a small puzzle. The program below will compile and run on some compilers but will\ not compile on others. main() { int *p; p = (int *) malloc(1024); test_it(p); } test_it (x) int (*x)[]; /* If a dimension is specified all compilers will accept it */ { int i; for (i=0; i < 10; ++i) (*x)[i] = i; /* x++; */ } The parameter 'x' in test_it without dimensions works on some compilers but others complain incomplete array'. I can understand that the compiler is trying to guess the size of the rows in the array. But that should come only when the commented x++ is used. Without the dimension all compilers generated an increment of 'int' size for 'x++' but with the dimension it was the size of dimension * int size. Does ANSI specify anything in this regard? |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| | Mr. R.L.K. Dattatri (408) 446-2110 (W) |~~~~~| | | Opus Systems (408) 243-5140 (H) |_____| | | 20863 Bldg 400 |\ | |/ |~~\ | | Stevens Creek, Cupertino | \ [___|\ | | | | California, 95014 \ | | | | E-mail: {uunet,sun}!opusys!rlkd FAX: (408) 446-5009 \ |__/ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
chris@mimsy.UUCP (Chris Torek) (08/25/89)
In article <404@opusys.UUCP> rlkd@opusys.UUCP (R.L.K.Dattatri) writes: >Here is a small puzzle. >The program below will compile and run on some compilers but will >not compile on others. This is a big hint as to the effect that you have written an incorrect program. (Many compilers do not catch some forms of incorrect program.) >main() >{ > int *p; > > p = (int *) malloc(1024); > test_it(p); >} >test_it (x) >int (*x)[]; >/* If a dimension is specified all compilers will accept it */ >{ > int i; > > for (i=0; i < 10; ++i) > (*x)[i] = i; > /* x++; */ >} Here is what the 4.3BSD-tahoe lint has to say about it. tt.c: malloc value used inconsistently llib-lc(288) :: tt.c(5) test_it, arg. 1 used inconsistently tt.c(11) :: tt.c(6) malloc value declared inconsistently llib-lc(288) :: tt.c(5) Alas, it does not catch the declaration `int (*x)[]' itself, only the fact that it differs from the type of p() in the call two lines above. >The parameter 'x' in test_it without dimensions works on some compilers >but others complain incomplete array'. The others are correct. You may not elide the dimensions from []s except in a few peculiar situations. Here `T' stands for a simple type or pointer, structure, or union type: extern T array[]; /* refers to an array of unknown size which must be defined elsewhere; sizeof(array) is illegal (many compilers give 0) */ Or T fn(T array[]) { ... /* declares a pointer! */ >I can understand that the compiler is trying to guess the size of the rows >in the array. But that should come only when the commented x++ is used. Not necessarily: it is possible that the size and shape of a pointer to an array depends on the size of the array. (I have never heard of such a machine, but one cannot rule it out offhand.) Note that in normal C usage, one keeps a pointer to an array element in order to get at an array, rather than a pointer to the whole array. >Without the dimension all compilers generated an increment of 'int' size for >'x++' but with the dimension it was the size of dimension * int size. I would expect more compilers to increment x by zero (4BSD PCC does). >Does ANSI specify anything in this regard? The proposed standard suggests that programmers not write such declarations. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
dfp@cbnewsl.ATT.COM (david.f.prosser) (08/25/89)
In article <404@opusys.UUCP> rlkd@opusys.UUCP (R.L.K.Dattatri) writes: >Here is a small puzzle. The program below will compile and run on some >compilers but will not compile on others. > >main() >{ > int *p; > p = (int *) malloc(1024); Since there is no visible declaration for malloc(), it must be assumed to return an int. Since it actually returns a void * (equivalent in this case to char *), it is quite possible that a "garbage" int value is consequently converted to int *. (For example, most 68k implementations return pointer values in a different register than integral values.) > test_it(p); >} >test_it (x) >int (*x)[]; A pointer to an int was passed to test_it(). This parameter declaration is for a pointer to an unspecified-sized array of int. These two are not equivalent, even though the number of indirection necessary to get to an int may be the same. >/* If a dimension is specified all compilers will accept it */ >{ > int i; > for (i=0; i < 10; ++i) > (*x)[i] = i; > /* x++; */ >} > >The parameter 'x' in test_it without dimensions works on some compilers >but others complain incomplete array'. >I can understand that the compiler is trying to guess the size of the rows >in the array. But that should come only when the commented x++ is used. >Without the dimension all compilers generated an increment of 'int' size for >'x++' but with the dimension it was the size of dimension * int size. > >Does ANSI specify anything in this regard? (Follow-up directed to comp.std.c.) You are correct that the length of the array is only necessary in this example if the "x++;" statement is included. Pointers to unspecified-sized arrays are valid in the pANS. Existing implementation were of varying minds with respect to pointers to arrays. For example, some took a construct such as ``&array_name'' and slapped your hand with a warning stating that the & was ignored since it was "incorrect". This is one of the areas where the pANS has helped the language. Dave Prosser ...not an official X3J11 answer...
thomas@advent.uucp (06/18/91)
The following is an interesting 'C' puzzle.
Consider this typical switch statement, typical except that
'default' is misspelled 'defalut'! What is interesting is that
any C compiler will not and should not give you a syntax error.
Why?
switch (cmd)
{
case GO:
...
break;
case STOP:
...
break;
defalut:
printf ("Unknown command\n");
break;
}
(Hint: It is bad programming practice to jump into the
middle of a switch statement.)
thomas
svec5@menudo.uh.edu (T.C. Zhao) (06/20/91)
In article <4007@d75.UUCP> thomas@advent.uucp () writes: > > The following is an interesting 'C' puzzle. > Consider this typical switch statement, typical except that > 'default' is misspelled 'defalut'! What is interesting is that > any C compiler will not and should not give you a syntax error. > Why? > > > switch (cmd) > { > case GO: > ... > break; > case STOP: > ... > break; > defalut: > printf ("Unknown command\n"); > break; > } Well, it depends. If defalut is never referenced, some compilers with certain switches might produce a warning: unreferenced label or unreachable code. I have not seen any C compiler like this( it is my impression that Fortran compiler tends to warn this kind of unreferenced stuff), but I wish my compiler would warn.
yamada@stego.ifa.hawaii.edu (Hubert Yamada) (06/20/91)
In article <1991Jun20.010011.18425@menudo.uh.edu> svec5@menudo.uh.edu (T.C. Zhao) writes: >In article <4007@d75.UUCP> thomas@advent.uucp () writes: >> >> The following is an interesting 'C' puzzle. >> Consider this typical switch statement, typical except that >> 'default' is misspelled 'defalut'! What is interesting is that >> any C compiler will not and should not give you a syntax error. >> Why? [Example deleted] > >Well, it depends. If defalut is never referenced, some compilers >with certain switches might produce a warning: unreferenced label >or unreachable code. I have not seen any C compiler like this( it is >my impression that Fortran compiler tends to warn this kind of >unreferenced stuff), but I wish my compiler would warn. Actually, I don't know of any C compiler that _won't_ tell you about this error, if you set the warning level reasonably high. With UNIX cc, setting the warning level high enough == use lint. (To avoid flames: I'm not saying that such C compilers don't exist, or even that they aren't common, just that none of the compilers that I use have that problem.) Unix gcc (1.39): gcc -Wall temp.c:16: warning: label `defalut' defined but not used Sun OS 4.1 lint: lint temp.c(16): warning: defalut unused in function xxx Microsoft C 6.0: cl -WX temp.c(20) : warning C4102: 'defalut' : unreferenced label PC lint (Gimpel Software): lint temp.c(19) : Info 744: switch statement has no default temp.c(20) : Warning 563: defalut (line 16) not referenced -- **************************************************************************** Hubert Yamada Internet: yamada@galileo.ifa.hawaii.edu (or yamada@uhunix.uhcc.hawaii.edu) Bitnet: yamada@uhunix.bitnet
Dave.Harris@f14.n15.z1.fidonet.org (Dave Harris) (06/22/91)
In a message of <Jun 20 21:55>, thomas@advent.uucp (1:114/15) writes: > switch (cmd) > { ... > defalut: > printf ("Unknown command\n"); > break; > } I glad to see I am not the only sucker that was bitten by this at one time. Its just another label as far as C is concerned (ie goto defalut;) -- Uucp: ...{gatech,ames,rutgers}!ncar!asuvax!stjhmc!15!14!Dave.Harris Internet: Dave.Harris@f14.n15.z1.fidonet.org
martin@mwtech.UUCP (Martin Weitzel) (06/22/91)
In article <13544@uhccux.uhcc.Hawaii.Edu> yamada@stego.ifa.hawaii.edu (Hubert Yamada) writes: >In article <1991Jun20.010011.18425@menudo.uh.edu> svec5@menudo.uh.edu (T.C. Zhao) writes: >>In article <4007@d75.UUCP> thomas@advent.uucp () writes: >>> >>> The following is an interesting 'C' puzzle. [...] >> >>Well, it depends. If defalut is never referenced, some compilers >>with certain switches might produce a warning: unreferenced label [...] >Actually, I don't know of any C compiler that _won't_ tell you about >this error, if you set the warning level reasonably high. With UNIX >cc, setting the warning level high enough == use lint. [...] Using lint only works if you are in the happy situation that your compiler (together with its header-files) is not yet so much ANSI-fied that your lint becomes unusable. (I'm sometimes forced to use such a beast; it's halfway down the road to ANSI-C. I like to profit from function prototypes, but sadly enough the lint on this system is the "old" one, which doesn't know anything of all that.) BTW: Here's another bug with a switch statement involved, I've once been tracing this for some hours: enum { RED, BLUE, GREEN } colour; ... /* assign valid value to colour */ ... switch (colour) { RED: ....; break; BLUE: ....; break; GREEN: ....; break; } Of course, finding the bug involved isolating this piece of code and finding out why `colour' changed its value away from one of `RED', `BLUE', or `GREEN', which I *thought* was the reason that no branch of the switch got ever executed ... (I confess: I didn't see the light until I had some printf-s immediatly before and after the switch which showed the value of `colour' in decimal and proved it beeing correct all the time.) -- Martin Weitzel, email: martin@mwtech.UUCP, voice: 49-(0)6151-6 56 83
martin@mwtech.UUCP (Martin Weitzel) (06/22/91)
In article <4007@d75.UUCP> thomas@advent.uucp () writes: > The following is an interesting 'C' puzzle. [...] > defalut: defau1t: Written this way ----^---- it makes the bug even more invisible on many terminal screens and printouts ... :-) -- Martin Weitzel, email: martin@mwtech.UUCP, voice: 49-(0)6151-6 56 83
yamada@stego.ifa.hawaii.edu (Hubert Yamada) (06/25/91)
[This quote been edited to shorten it] In article <1173@mwtech.UUCP> martin@mwtech.UUCP (Martin Weitzel) writes: >In article <13544@uhccux.uhcc.Hawaii.Edu> yamada@stego.ifa.hawaii.edu (Hubert Yamada) writes: >>Actually, I don't know of any C compiler that _won't_ tell you about >>this error, if you set the warning level reasonably high. With UNIX >>cc, setting the warning level high enough == use lint. > >Using lint only works if you are in the happy situation that your >compiler (together with its header-files) is not yet so much ANSI-fied >that your lint becomes unusable. (I'm sometimes forced to use such a beast; >it's halfway down the road to ANSI-C. I like to profit from function >prototypes, but sadly enough the lint on this system is the "old" one, >which doesn't know anything of all that.) This is _so_ true. Fortunately, the ansi compilers that I've dealt with had better local error checking than cc. But I haven't found any compiler that does global error detection as well as lint does. I've taken the approach of writing code that compiles correctly under ansi C compilers and under traditional C compilers. In order to do this I've been forced to use some macros that modify declarations and prototypes depending on the type of compiler is. This lets me have the advantage of both. But the macros are ugly and clumsy, and the resultant code is _very_ugly_. -- **************************************************************************** Hubert Yamada Internet: yamada@galileo.ifa.hawaii.edu (or yamada@uhunix.uhcc.hawaii.edu) Bitnet: yamada@uhunix.bitnet
mcdaniel@adi.com (Tim McDaniel) (06/25/91)
In article <1173@mwtech.UUCP> martin@mwtech.UUCP (Martin Weitzel) writes:
Using lint only works if you are in the happy situation that your
compiler (together with its header-files) is not yet so much
ANSI-fied that your lint becomes unusable.
At this point, I will put in my monthly plug for FlexeLint/PC-Lint
from Gimpel Software. (Disclaimer: I'm just a satisfied customer; I
have no financial or other interest in Gimpel Software, except for
wanting future releases. 8-)
Gimpel Software's FlexeLint is fully ANSI-compatable. It can also
handle most pre-ANSI constructs and semantics. It is an excellent
product, primarily because each message can be individually turned on
or off, within parts of a source file or for particular symbols or
files.
Gimpel Software
3207 Hogarth lane
Collegeville, PA 19426
telephone: 1 215 584 4261
It can be run on SUNs, VAXen, PCs (PC-Lint), et cetera.
--
"Of course he has a knife; he always has a knife. We all have knives.
It's 1183 and we're barbarians." -- Eleanor of Aquitaine, "A Lion in Winter"
Tim McDaniel Applied Dynamics Int'l.; Ann Arbor, Michigan, USA
Internet: mcdaniel@adi.com UUCP: {uunet,sharkey}!amara!mcdaniel
chaplin@keinstr.uucp (chaplin) (06/26/91)
In article <4007@d75.UUCP> thomas@advent.uucp () writes: > > The following is an interesting 'C' puzzle. > Consider this typical switch statement, typical except that > 'default' is misspelled 'defalut'! What is interesting is that > any C compiler will not and should not give you a syntax error. > Why? > > > switch (cmd) > { > case GO: > ... > break; > case STOP: > ... > break; > defalut: ^^^^^^^^ This is a valid statement label, useful as the target of a goto statement. _K&R_ 2nd Edition page 66. > printf ("Unknown command\n"); > break; > } > > (Hint: It is bad programming practice to jump into the > middle of a switch statement.) > >thomas That was almost too easy. BTW, according to _K&R_ it is bad programming practice in almost all cases to use goto, and since the *only* use of a label is as the target of the goto statement (_K&R_ 2nd ed. page 222), labels are almost always bad programming practice. You did not intend this as a label though. Hmmm... an interesting problem. I'm not sure how much help lint would be, but I do know that Saber C would detect this as a label defined but never referenced. -- Roger Chaplin / Instruments Division Engineering / "Though I'd been lost now I chaplin@keinstr.uucp / CI$: 76307,3506 / felt I was found when He #include <disclaimer.h> / looked at me with His #include "disclaimer.h" /* cover all bases */ / forgiving eyes." - Michael Card