1

Are the following declarations correct?

Outside any function:

int a; //external by default
extern int a; //explicitly extern
static int a; //explicity static
const int a; //static by default
static const int a; //explicitly static
extern const int a; //explicitly extern

Inside a function:

int a; //auto by default
static in a; //explicity static
const int a; //static by default
static const int a; //explicitly static
  • `const` has no effect on storage duration or linkage, ie the same rules apply to `const` and non-`const` variables... – Christoph May 04 '12 at 19:46
  • see also the example at http://port70.net/~nsz/c/c99/n1256.html#6.9.2 about file-scope definitions... – Christoph May 04 '12 at 20:02

3 Answers3

2

Close.

Anything at global scope (ie: outside a function) is static by default.

eg:

//main.c
int myVar;  // global, and static

int main(void) {
  ...
  return 0;
}

//morecode.c
extern int myVar; //other C files can see and use this global/static variable

However, if you explicitly declare something at the global scope as static, not only is it static, but it is only visible inside that file. Other files can't see it.

//main.c
static int myVar;  // global, and static

int main(void) {
  ...
  return 0;
}

//morecode.c
extern int myVar; // compiler error; "myVar" can only be seen by 
                  // code in main.c since it was explicitly 
                  // declared static at the global scope

Also, nothing is "extern" by default. You typically use extern to access global variables from other files, provided they weren't explicitly declared static as in the example above.

const only implies that the data cannot change, regardless of it's scope. It does not imply extern, or static. Something can be "extern const" or "extern", but "extern static" doesn't really make sense.

As a final example, this code will build on most compilers, but it has a problem: myVar is always declared "extern", even in the file that technically creates it. Bad practice:

//main.c
extern int myVar;  // global, and static, but redundant, and might not work
                   // on some compilers; don't do this; at least one .C file
                   // should contain the line "int myVar" if you want it 
                   // accessible by other files
int main(void) {
  ...
  return 0;
}

//morecode.c
extern int myVar; //other C files can see and use this global/static variable

Finally, you might want to cover this post on the various levels of scope if you are not already familiar with them. It will likely be helpful and informative to you. Good luck!

Terminology definition - Scope in C application

The person who answered this question of mine on scope did a good job, in my opinion.

Also, if you declare something static within a function, the value remains between function calls.

eg:

int myFunc(int input) {
  static int statInt = 5;
  printf("Input:%d  statInt:%d",input,statInt);
  statInt++;
  return statInt;
}

int main(void) {
  myFunc(1);
  myFunc(5);
  myFunc(100);
  return 0;
}

Output:

Input:1  statInt:0
Input:5  statInt:1
Input:100  statInt:2

Note that the use of a static variable within a function has a specific and limited number of cases where they are useful, and generally aren't a good idea for most projects.

Community
  • 1
  • 1
Cloud
  • 18,753
  • 15
  • 79
  • 153
  • Is `static const int i;` a valid statement? –  May 04 '12 at 20:11
  • Yes. If you do that at global scope, you've created a const variable that only can be access within that file. Furthermore, the value can only be set at define time, so the only way to use that which would make sense would be something like: static const int ConsCanOnlyBeSeenInThisFile = 1; for example. If you do that within a function, it has a similar effect, but can only be seen at function scope. Remember, if you set a variable within a function to be static, its value stays the same between calls. – Cloud May 04 '12 at 22:04
1

One misconception you have appears to be that extern is the opposite of static. This is not the case. You have this:

int a; //extern by default

That's not "extern by default". An extern declaration means that the actual variable definition is elsewhere. So if you have this in your source file:

extern int a;

Then somewhere else you have another source file with:

int a;

Otherwise, if you compile your code you'll get:

/tmp/cc3NMJxZ.o: In function `main':
foo.c:(.text+0x11): undefined reference to `a'
collect2: ld returned 1 exit status

static outside of a function definition means that the variable is only visible to other code defined in the same file. The absence of static means that the variable is visible globally to code that might link against your object file.

I am less certain, but I don't believe that const implies static. That shouldn't be too hard to test.

...and indeed, a very simple test confirms that const does not imply static.

larsks
  • 277,717
  • 41
  • 399
  • 399
  • `extern` doesn't necessarily imply that the definition is in another file. Both the extern declaration and the definition can be in the same file. `extern` just means that `The definition of this variable exists somwhere ( which can be anywhere ) – Pavan Manjunath May 04 '12 at 19:49
  • *extern by default* is correct insofar as file-scope variables have external linkage by default; however, the connection between linkage and the specifiers `extern` and `static` is not as simple as one might expect... – Christoph May 04 '12 at 19:50
  • @Christoph, I'm not sure I understand what you're saying. There's a big difference between `extern int a` and `int a`, unless I'm confused, which argues that `int a` cannot be called "extern by default". – larsks May 04 '12 at 19:51
  • 2
    `int a;` at file scope is a tentative definition with external linkage, `int a = 42;` and `extern int a = 42;` are both equivalent external definitions and `extern int a;` is a declaration (*not* a definition) with external linkage if it's the first declaration in the translation unit -- otherwise, it refers to the previous declaration; a bit of a mess, really... – Christoph May 04 '12 at 19:54
  • @larsks It was a typo. I meant 'external' and not 'extern'. –  May 04 '12 at 19:55
1

You have to separate the concepts of storage duration and linkage. extern and static, in various contexts, can have effects on both of these properties and other effects but aren't the sole determiner of any of them.

At file scope


int a;

This is a tentative definition. a has static storage duration and external linkage.


extern int a;

A declaration but not a definition. static storage duration and external linkage (or the linkage determined by a prior declaration if one is visible).


static int a;

A tentative definition. static storage duration and internal linkage.


const int a;

A tentative declaration. static storage duration and external linkage (unlike C++).


static const int a;

A tentative definition. static storage duration and internal linkage.


extern const int a;

A declaration and not a definition. static storage duration and external linkage (or the linkage determined by a prior declaration if one is visible).


In block scope


int a;

Definition. automatic storage duration and no linkage.


static int a;

Definition. static storage duration and no linkage.


const int a;

Definition. automatic storage duration and no linkage. (I think this is strictly legal but not very useful as you can't modify a's indeterminate initial value without causing undefined behavior.)


static const int a;

Definition. static storage duration and no linkage. (Again, not very useful!)

CB Bailey
  • 755,051
  • 104
  • 632
  • 656
  • small correction: `extern int a;` at file scope only has external linkage if there's no previous declaration with internal linkage; also missing from both question and answer: block-scope external declarations – Christoph May 04 '12 at 21:05
  • @Christoph: True, I was assuming that these were the first (or only) declarations in their respective scopes. – CB Bailey May 04 '12 at 21:07
  • also, I wouldn't say block-scoped `static const int a;` is useless - objects with static storage duration are implicitly zero-initialized, so the value is well-defined; I use such variables regularly, eg to initialize allocated objects – Christoph May 04 '12 at 21:11
  • @Christoph: Fair enough, although the `int` version isn't _that_ useful as you may as well use `0` (unless you have a really good name for zero that has a special meaning in some domain). – CB Bailey May 04 '12 at 21:27