views:

581

answers:

6

Some times we need to pre-declare a static variable and then use it. But the variable name of this declaration may be wrong, and the compiler can not detect it, oops!

Example:

/* lots of codes */
static some_type some_name; /* pre-declaration */
                            /* but it may define "some_name" */
/* use some_name */

/* lots of codes */

static some_type someName = initialization; /* definition */
/* use someName */

/* lots of codes */

"some_name" and "someName" are different, we use a wrong variable at the begin. If the pre-declaration statement does not define any thing, the compiler will detect the mistake.

So, how to declare a static variable but not define it? How can I change the pre-declaration to a new one which makes compiler can detects wrong names?

+10  A: 
static some_type some_name; /*definition */

The static variable some_name has been initialized by 0; it is the definition, not just a declaration.

IMO, a static variable cannot be just declared in C using extern specifier as its linkage is always internal.

Prasoon Saurav
I don't think you're using "IMO" properly. That doesn't sound like an opinion.
Chris Lutz
It _is_ Prasoon's opinion; it also aligns with the standard, so his opinion is correct (according to the standard).
Jonathan Leffler
+8  A: 

gcc will give a warning in the case you've described:

./x.c:3010: warning: 'someName' defined but not used

Solution: Do what you're currently doing, but don't ignore compiler warnings ;)

Edit:

With your updated question: No, I don't believe there is a way to simply declare a static variable (without also defining it).

The common solution is just to make sure all your global scope variables are declared once only, with an initialiser if they need it.

caf
"someName" is also being used, I have change my post a little, thanks.
NjuBee
A: 

Do you need to pre-declare the variable? If not, then put the initializer on the only declaration. If your initializer is not a constant (which would require C++, not C, IIRC), then I can understand why you need to pre-declare it before some functions that use it. But then everything you need for the initializer could be pre-declared before it.

So put your constant defs and static variables up at the top of each file, so your initializer for the static can come right after the constants. Then you don't need a separate initialization line.

In any other case, caf's right: It can be worth getting your code to compile with gcc just to get the benefit of its warnings. I've done that for g++ for an MFC GUI in C++. (compile, not run!)

AFAIK C doesn't have a way to write a weak definition that will produce an error if there isn't a definition with an initializer later. There's always an implicit 0, since the variable goes in the BSS section.

Peter Cordes
A: 

If I understand your problem maybe your just not facing it the right way.

Would you not be better with extern SomeType someVar_; which says to your program, I know that this variable will be known, but I don't want to tell you what it is now.

You can therefore, in a separate file declare your variable say

static SomeType SomeVar_;

In your file, put

extern SomeType SomeVar_

And than put the initialization wherever you want.

Balls-of-steel
That will cause a linker error, as the `static` definition has internal linkage and cannot be reached by the file where it is declared using `extern`.
Ben Voigt
A: 

A little background:

As others have pointed out, static variables are have internal linkage, which means that they can only be used in the same "compilation unit" or source file. That means you cannot declare it in a header file, assign a value to it in one compilation unit, and expect that value to appear in another.

When you initialize a global variable (static or not), the compiler simply puts the initial value into the executable file at the memory location allocated for the variable. In other words, it always has an initial value. Of course you can always override the value later by using an assignment statement.

Suggestions:

If you really don't know the value of the variable at compile-time, then you should assign it dynamically in your initialization function.

static some_type some_variable; /* = 0 by default */

/* some code */

void MyInitializations()
{
    some_variable = some_value;
}

If you want to declare the variable in one place, say a header file, and define it in a source file, then you should use an 'extern' declaration which tells the compiler to not worry about where the variable is. The linker will find the location of the variable much like it finds a function in another file and fill in the address.

Header:

extern some_type some_variable;

Source file 1:

void UseSomeVariable()
{
    x = some_variable;
}

Source file 2:

some_type some_variable = some_value;

/* possible also uses some_variable */

If you just want to declare the variable in one place and define it in another, don't use the 'static' keyword. The downside of this is that you can't use the same global variable in different compilation units (.c files) and you can't use it in a header file.

antonm
+2  A: 

It is not possible to create a non-defining declaration (i.e. "pre-declare" in your terminology) of an object with internal linkage in C language.

As close as you can get to that is a tentative definition, which is what you have in your example. But in case of a typo tentative defintion will implictly produce an independent definition, not a linker error.

AndreyT