On 10/04/2012 06:23 AM, lipska the kat wrote:
> On 03/10/12 19:13, lipska the kat wrote:
>
> First of all let me say once again how much I appreciate all your
> responses. A seed of doubt has been planted in my mind WRT the
> 'correctness' of any C code that I have written/will write at any time
> in the future. I think this must be a 'good thing' although the
> implication is that before I can be as certain as it's possible to be
> that any program is 'correct' I need to have read, understood and
> inwardly digested the entire language specification. A rather daunting
> prospect but I will certainly make a start ... when I can figure out
> what standard I should be reading (C89, C90, C99 or C11)
>
> According to man gcc on my Ubuntu Linux 12.04 64 bit machine
> 89,90 are fully supported whereas support for 99 onwards is 'limited'
> Compiling with the -ansi switch compiles to the 89/90 spec which
> reinforces my opinion that 90 is the one for me.
That's a safe choice; I prefer C99 myself, and gcc's support for C99 is
almost complete.
> There are also a whole bunch of gnu dialects
> but my brain imploded at this point so I went to the pub
I recommend learning standard C first. Learn about and use the Gnu
dialects later, if you want to - but avoid using gnuisms unless you're
absolutely certain that your code will never be compiled with anything
other than gcc.
> Anyway, I think I've figured out the extern thing in terms of my very
> simple example. I do have one small observation which I will make after
> the re-factored code, you have been very generous with your time so far
> so apologies for posting this listing again.
>
> ============= Code ===============
>
> /* foo.h */
> /* explicit _declaration_ of foo */
> extern int foo;
>
> void fooset(int f);
> int fooget(void);
> void fooinc(void);
>
> /* extmain.c */
> #include <stdio.h>
> #include "foo.h"
>
> /* global variable */
> /* implicit definition of foo */
> /* set get and inc can't see foo if this is not here */
> int foo;
>
> int main(int argc, char **argv){
>
> /* explicit definition of foo */
> foo = 0;
>
> fooset(10);
> printf("foo is %d\n", fooget());
>
> fooinc();
> printf("foo is now %d\n", fooget());
>
> return 0;
> }
>
> /* fooset.c */
> #include "foo.h"
>
> void fooset(int f){
> foo = f;
> }
>
> /* fooget.c */
> #include "foo.h"
>
> int fooget(void){
> return foo;
> }
>
> /* fooinc.c */
> #include "foo.h"
>
> void fooinc(void){
> ++foo;
> }
>
> Observation:
>
> The word 'extern' doesn't seem to be required
>
> /* foo.h */
> extern int foo;
>
> OR
>
> /* foo.h */
> int foo;
>
> Both work
The fact that the second one works is due to a feature of gcc that a
conforming implementation of C is not required to have: gcc merges all
of the multiple external definitions of 'foo' into a single definition.
As others have already mentioned, this behavior can be turned off by
selecting the -fno-common option.
> At this point it seems to me that the only reason to use
> the word extern is as an aid to program documentation.
No, it makes the behavior of your code well-defined, which means you can
count on it working even if you use some other fully-conforming
implementation of C to compile it.
--
James Kuyper