spartan3wiz wrote, On 25/03/08 19:51:
Hi,
I have some example C code and would like to know what a "good"
behaving C compiler would do. This is because I'm writing my own C-
compiler that will end up as open-source sometime in the future.
I think it would be nice if you went against the norm and produced a
compiler that by default conformed to the C standard with a high level
of additional warnings and the user had to explicitly switch on
extensions and turn the warning level down if required.
Also, as you are starting now it would probably a good thing if you
aimed for C99 conformance (i.e. the standard released in 1999) rather
than the old C89/C90/C95 standard.
Normally I use Microsoft Visual C++ 2005 C-compiler for testing
because I'm a windows-based programmer. The below behavior describes
Visual studio only conforms to C95 and by default has a number of
extensions enabled. You might consider also using gcc to compare against.
Also, you should really get a copy of the C standard, drafts are
available for free, including one which (modulo errors) is the latest
standard + all current updates. See
http://clc-wiki.net/wiki/c_standard
how Microsoft's C compiler behaves when using the "/TC" command line
parameter to restrict the C/C++ compiler to only accept C-like syntax
and using "/W4" to get the highest warning level.
Example Code 1:
-snip-
void main(void)
void main is not one of the standard forms of main. You are allowed to
accept it as an extension if you choose, but I think following gcc's
lead and at elast producing a warning would be better.
C99 has removed implicit int, so calling test before declaring it now
requires a diagnostic. Even if you want to implement the older standard
then at least a warning would be useful.
Had you included a non-prototype declaration before the call, e.g.
int test();
then even under C99 no diagnostic (error or warning) would have been
required. However warning that there was no prototype in scope (a
prototype also includes parameter types) would be useful. It would also
be useful if you remembered how it had been called and produced an error
when you reached the definition if it did not match (remember to allow
for default argument promotions etc).
Also note that calling a function with an incorrect number of parameters
invokes "undefined behaviour". What this means to you as an implementer
is that you don't have to bother making it work.
}
int test(int a)
{
return 0;
}
-snip-
This code compiles with 2 warnings:
warning C4013: 'test' undefined; assuming extern returning int
This is useful but not required according to C95 which is what the
compiler conforms to (modulo bugs) but it is useful. You should note
that you are allowed to produce diagnostics (e.g. warnings) for anything
you like as far as the C standard is concerned.
warning C4100: 'a' : unreferenced formal parameter
This is useful but not required by any version of the C standard.
However it is useful to be able to disable the warning because some
times there are good reasons for not using a parameter.
So it uses the call for test( ) as a declaration (with implicit return
type 'int'), is this standard?
It was in C89/C95/C95 but is no longer valid in C99.
Even though the body uses an inparameter of 'int' it still compiles
and executes correctly, is this standard?
It is *allowed* to do what the programmer expected, but it is not
*required* to do what the programmer expected.
You can actually send any
number of parameters and any type and it still compiles and runs... it
does seem to behave more like standard C if I omit the "/TC" why is
that?
You are incorrect in believing it behaves more like standard C without
/TC. It would still be behaving entirely within what the standard
allowed if it failed to compile the above program, or if the compiled
program printed, "your mother is a bloated warthog" or reformatted your
hard disk.
--------------------------------------------------------
Example Code 2:
-snip-
int test(int a)
{
return 0;
}
void main(void)
{
test();
}
-snip-
This code compiles with 1 error and 1 warning:
warning C4100: 'a' : unreferenced formal parameter
This warning is not required but is useful.
error C2198: 'test' : too few arguments for call
A diagnostic is required in this instance (it does not have to be
meaningful and it does not have to be an error). The reason a diagnostic
is required in this instance is that a prototype (which also happens to
be a definition) is in scope.
This seems more correct as the number of inparameters in the function
declaration does not match with the number of inparameters in the
function call ..
See comments above.
Your first port of call should be the standard, although that can be
hard to read.