E
E. Robert Tisdale
Chris said:Someone notes that, if one follows the "comp.lang.c accepted
practice" of not casting malloc() return values, and uses most
ordinary C89/C90 compilers in their default non-warning modes
so that one gets only the required diagnostics, forgetting to
For example, if one were to write:
struct zorg *new_zorg(double degree_of_evilness) {
struct zorg *new = malloc(sizeof *new);
new->degree = degree_of_evilness;
return new;
}
and feed it to the Generic C Compiler, one might get:
% cc -c zorg.c
zorg.c: In function `new_zorg':
zorg.c:4: warning: initialization makes pointer from integer without a cast
The problem is that you are using an inferior C compiler
or that you have forgotten the appropriate options:
> cc -Wall -c zorg.c
zorg.c: In function `new_zorg':
zorg.c:6: warning: implicit declaration of function `malloc'
zorg.c:6: warning: initialization makes pointer from integer \
without a cast
This provides an *explicit* warning
of the implicit declaration of function `malloc'.
It is certainly true that this warning leaves something to be
desired. The problem is not making a "pointer from integer",
but rather with "malloc never explicitly declared, thus implicitly
declared instead". Nonetheless, this is hardly a *new* problem:
% cc -c oops.c
oops.c:6: syntax error before `for'
% cat oops.c
/* kind of like strlen() but returns an int *./
int like_strlen(const char *p) {
int i;
/* we just need to find the first p that is '\0' */
for (i = 0; p != 0; i++)
continue;
return i;
}
There is nothing wrong on line 6, nor line 5, nor 4 (blank), nor
3, nor even line 2 -- the problem is all the way back on line 1,
where a typographic error inserted a period between the * and /
meant to close the comment. There are all kinds of constructs like
this, where a compiler issues the wrong message. Programmers *need*
to learn not to trust where the machine points, in the same way
that automobile mechanics need to learn not to assume that, if the
On Board Diagnostics in an engine computer says "oxygen sensor
failure", it is not necessarily the sensor itself that failed.
(The problem can be in the wire connecting the sensor to the
computer. The sensor is a "replacement item" -- the ones in the
exhaust system in particular may have only a few years' lifetime
-- so the diagnostic is *usually* right, but not always.)
It is always a good idea to compare the machine's complaint against
what you (believe you) know to be the case. If the machine says
"you are making a pointer from an integer", but you know malloc()
does not return an integer, then you should ask yourself: where is
this integer? Why does the compiler believe there is an integer
here? Then, if all else fails, you could even post to comp.lang.c:
"I have this C code here, and the compiler is giving me a
message involving an `integer' when there is no integer.
Why is that?"
Ideally, you should include a complete, compilable chunk of code,
and the exact text of the error or warning message, too. But the
goal here -- besides fixing the problem -- is learning why a C
compiler might think there is an integer here, when you are certain
there is none. Then you will hear all about "implicit int function
declarations", why they are bad, that your compiler needs a tuneup
(e.g., "-Wmissing-declarations") if not a complete replacement,
and of course the inevitable cascade of "don't cast malloc in C /
compile your C code with an Ada-I-mean-C++-compiler" flamage.
I know that you worked a long time on this
but it is a fallacious argument.
http://www.don-lindsay-archive.org/skeptic/arguments.html
Your first example shows that you are using an inferior C compiler
or that you didn't know about the option that would give you
and explicit diagnostic of the true problem
or that you knew about the option and suppressed it:
Argument By Half Truth (Suppressed Evidence)
Your second example is a straw man and a bad analogy
because, unlike the first example, the compiler cannot recognize it
as an *acceptable* C program.
It probably isn't reasonable to expect a C compiler
to parse comments and diagnose typographical errors.
You can't compile your second example, but the first example:
#include<stdio.h>> expand zorg.c
struct zorg {
double degree;
};
struct zorg *new_zorg(double degree_of_evilness) {
struct zorg *new = malloc(sizeof *new);
new->degree = degree_of_evilness;
return new;
}
int main(int argc, char* argv[]) {
struct zorg* p = new_zorg(666.0);
fprintf(stdout, "%f = p->degree\n", p->degree);
free(p);
return 0;
}
compiles:
zorg.c: In function `new_zorg':> cc -Wall -std=c99 -pedantic -o zorg zorg.c
zorg.c:8: warning: implicit declaration of function `malloc'
zorg.c:8: warning: initialization makes pointer from integer \
without a cast
zorg.c: In function `main':
zorg.c:16: warning: implicit declaration of function `free'
and links and runs:
666.000000 = p->degree> ./zorg
just fine on my system.