In article <news:c2mte5$au4$1...@zcars0v6.ca.nortel.com>Xiangliang Meng <xiangli...@hotmail.com> writes:>Could you explain a little more on why they are OK in a file scope, but the>second is invalid in blocks? What is the difference for the second between>in the file scope and in the block scope?

At the most important level, the reason is just "because the CStandards say so". The declaration of "t" above is invalid inblock scope because the rules of the C standard prohibit it; it isvalid in file scope -- and means the same as "char t[1]" if noother declaration overrides it -- because the rules of the CStandards say so.

Fundamentally, there is no particular reason it *has* to work thisway, and in the days before the first C standard (ANSI X3.159-1989,also known as "C89"), different C compilers had different rules.If you wrote "char t[];" at file scope, some compilers gave you anerror message and refused to compile your code. If the people whowrote the C89 standard had so chosen, they could have made this anerror. Instead, though, they decided to adopt a series of rulesthat give useful results in various cases where pre-C89 compilerssometime fell short.

In particular, the C89 folks invented (or borrowed) the concept ofa "tentative definition" of a variable. You can "tentatively"define a variable, which has the useful side effect of telling theC compiler that it is going to exist sooner or later, so that youcan use the name of the variable. Eventually you also define thevariable "for real", possibly giving it an initial value.

Consider the example of a circular queue data structure:

struct queue { struct queue *forw, *back; some_type data; };

Queues like this often have a "dummy" head node and then zero ormore data nodes. Suppose you want to provide an initial singledata node. How can you define two variables that will point toeach other?

If both variables are to have external linkage (i.e., are "globalvariables" in the sense people usually mean by the phrase "globalvariables"), you can, even in implementations predating the 1989C standard, write this code:

The first of these lines announces to the C compiler: "there is avariable named initialnode, of type struct queue". This announcementis required in order to provide &initialnode as the initializerfor head.forw and head.back.

But what if, on the other hand, both of these variables are to bedeclared "static" (i.e., have internal linkage)? You must write:

static struct queue initialnode;

("static" instead of "extern"). Many pre-C89 C compilers tookthis as the *definition* of the variable initialnode, meaningthe same thing as:

static struct queue initialnode = { 0, 0, 0 };

If you follow this with a later:

static struct queue initialnode = { &head, &head, INITIAL_DATA };

you just got an error. You cannot write "extern struct queueinitialnode; ... static struct queue initialnode = { ... };"either, as this is also an error.

The C89 solution to this problem is "tentative definitions", inwhich you simply write the definition with no initializer. Atentative definition is, in effect, "recorded" at the point of thedefinition and "remembered" until a corresponding actual (non-tentative)definition, or the end of the translation unit:

At the end of the translation unit, all the outstanding tentativedefinitions become actual definitions, initialized with "= { 0 }".This means that the declaration for t eventually becomes:

char t[] = { 0 };

which gives t a single element (so that sizeof(t) is 1*sizeof(char),which is just 1).-- In-Real-Life: Chris Torek, Wind River SystemsSalt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603email: forget about it http://web.torek.net/torek/index.htmlReading email is like searching for food in the garbage, thanks to spammers.