ptw (04/09/83)
What flag would one use with (4.1) lint to get it to tell you that char *string = input; for(; string != '\0'; string++) is an error? Seems to me that a character constant should not be allowed to be compared to a pointer. P. Tucker Withington Automatix Incorporated ...decvax!{wivax,genrad}!linus!vaxine!ptw (617) 667-7900 x2044
donn (04/10/83)
Reference: vaxine.115 What flag would one use with (4.1) lint to get it to tell you that char *string = input; for(; string != '\0'; string++) is an error? Seems to me that a character constant should not be allowed to be compared to a pointer. P. Tucker Withington Automatix Incorporated ...decvax!{wivax,genrad}!linus!vaxine!ptw (617) 667-7900 x2044 This is a tricky one. The problem is that in general character constants may NOT be compared to pointers -- in fact the only things that may legally be compared to pointers are other pointers and the integer 0 (C Reference Manual, Sections 7.6, 7.7). But the relational expression in the example is in fact testing the pointer "string" against the integer 0, since characters are promoted to integers in relational expressions (7.7); we don't have a type clash. You might expect at least a warning from the PCC or lint, however. Well, it turns out that the PCC is too clever. Since character values are always promoted to integer values in expressions, the PCC doesn't bother to save type information about character constants; they are treated as another way of expressing integers. (It's easy to see why this is done when you remember that multi-character character constants are permitted by the PCC. Notice that this is NOT in the standard.) By the time the error is reportable (routine chkpun() in trees.c) there is no way to tell that the user put '\0' instead of 0. Lint just re-uses the PCC code and thus it couldn't say anything useful about style or programming heuristics even if it wanted to. The only consolation is that this only happens when you are trying to compare with '\0'; any other character value would cause a warning. Donn Seeley UCSD Chemistry Dept. RRCF ucbvax!sdcsvax!sdchema!donn (619) 452-4016 sdamos!donn@nprdc
thomas (04/14/83)
4.1 lint complains about 0 not matching pointers on function calls, but nowhere else. This is weird! =Spencer
ark (04/15/83)
The comment was that lint complains about 0 not matching pointers in function calls but not elsewhere. This is correct. Consider: sometype *foo; foo = 0; The assignment has the same effect as foo = (sometype *) 0; 0 is guaranteed to be convertible to a pointer, and it is guaranteed that this resulting pointer will compare unequal to a pointer to any actual data object. The cast is unnecessary because the right hand side of an assignment is what some people call a "strong context": there is only one type that is legitimate in that context. Now consider: f(0) It is not possible, in general, to determine by inspection what type f expects unless the definition of f is handy. Suppose that f is: f (x) sometype *x; {...} and that it is compiled elsewhere. Now, an integer is being passed, WITHOUT CONVERSION, to a function that expects a pointer. You may say: So what? Won't some kind of implicit conversion take place? Well, maybe. On some machines, it is convenient to have 16-bit integers and 32-bit pointers. Saying f(0) definitely won't work on these machines; you must say f((sometype *) 0) instead. In C, an actual parameter is not a strong context.
lantz (04/23/83)
I've always wondered why NULL isn't defined in stdio as ((char *)0). Is there some good reason, or is just because on most systems it isn't necessary? This would make the call execl("whatever", "whatever", NULL); correct regardless of the relative sizes of integers and pointers. Philip Lantz duke!ucf-cs!lantz
guy (04/24/83)
If it were defined that way, if you had a routine "foo":
foo(bar)
int *bar;
{
if (bar == NULL)
do one thing;
else
do another;
}
and you wanted to call "foo" with a null pointer, you would either have to
say
foo((int *)0);
or say
foo(NULL);
in which case "lint" would bitch that you were passing a "char *" to a
routine that expected an "int *", or say
foo((int *)NULL);
in which case "lint" would bitch that you were trying to convert a "char *"
to an "int *" which is a Bozo No-No. Trouble is there *is* no such thing
as a "null pointer" in C; there is a null character pointer, and a null
int pointer, and a null struct proc pointer, and a null int() pointer, and...
Guy Harris
RLG Corporation
{seismo,mcnc,we13}!rlgvax!guy