8

Is the static keyword in C used only for limiting the scope of a variable to a single file?

I need to know if I understood this right. Please assume the following 3 files,

file1.c

int a;

file2.c

int b;

file3.c

static int c;

Now, if the 3 files are compiled together, then the variables "a" & "b" should have a global scope and can be accessed from any of the 3 files. But, variable "c" being static, can only be accessed from file3.c, right?

Does static have any other use in C ? (other than to limit the scope of a variable as shown above?)

chronodekar
  • 2,616
  • 6
  • 31
  • 36
  • 1
    variable a & b don't have visibility in other C files unless you "extern" them. – Murali VP Nov 25 '09 at 08:21
  • 2
    @Murali; not completely true, you'll run into linking problems if you define "int a;" in two files. – falstro Nov 25 '09 at 08:29
  • 1
    oh, and for the record. It's not scoped to the file, it's scoped to the compilation unit. It's quite possible to include a ".c" file in another ".c" file, or for that matter, declare an "int a;" in a .h file. It's not good style, but quite possible. – falstro Nov 25 '09 at 08:32
  • @Murali, then from a scope-perspective, the variables a,b & c are only visible in their respective files, regardless of the "static" keyword? So, the "static" in the above does nothing ? – chronodekar Nov 25 '09 at 08:36
  • 4
    @chronodekar: You seem to be suffering from a terminological mix-up. Unfortunately, most people here do. Please, stop mixing the therms "visibility", "scope" and "linkage". Identifiers are always visible in just one translation unit: from the point of declaration and to the end of the unit. The area where the identifier is visible is called "scope". I.e. "scope" and "visibility" is the same thing and it is always local to a single translation unit. Now, "linkage" is a more global concept. Linkage is the ability to link to the same object from a different translation unit. – AnT stands with Russia Nov 25 '09 at 08:56
  • 3
    Objects with external linkage can be linked to from another translation unit (by declaring them there). Objects with internal linkage cannot be linked to from another translation unit. That's what `static` controls - linkage. `static` does not affect scope (and visibility). – AnT stands with Russia Nov 25 '09 at 09:04

7 Answers7

16

The static keyword serves two distinct purposes in C, what I call duration (the lifetime of an object) and visibility (where you can use an object from). Keep in mind the C standard actually uses different words for these two concepts but I've found in teaching the language that it's best to use everyday terms to begin with.

When used at file level (outside of any function), it controls visibility. The duration of variables defined at file level are already defined as being the entire duration of the program so you don't need static for that.

Static variables at file level are invisible to anything outside the translation unit (the linker can't see it).

When used at function level (inside a function), it controls duration. That's because the visibility is already defined as being local to that function.

In that case, the duration of the variable is the entire duration of the program and the value is maintained between invocations of the function.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • 4
    What you called "visibility" is really called "linkage". Visibility is a completely different thing. "Visibility" is the same thing as "scope". `static` has no effect on visibility. `static` has no effect on scope. – AnT stands with Russia Nov 25 '09 at 08:35
  • Visibility is *not* the same thing as scope. The scope of a file-level variable ends at the end of the translation unit. It's visibility is available *outside* the translation unit when the linker can see it. I specifically used the word visibility to avoid the clash with scope. – paxdiablo Nov 25 '09 at 08:39
  • Visibility is more to do with the linkage, but in a term that's easier to explain to people than the dry language of the standard :-) – paxdiablo Nov 25 '09 at 08:41
  • Incorrect. You are inventing your own meaning for the term visibility. The term "visibility" is already taken in C language and it means the visibility of an identifier, i.e. its *scope* (defined in 6.2.1/2). What you are talking about is called *linkage* and it is never referred to as "visibility". Open the standard and read the definitions. Stop confusing people with made-up interpretations of stanadrd terms. – AnT stands with Russia Nov 25 '09 at 08:45
  • 2
    Yes, I am inventing my own term. If I'm teaching someone the *standard*, I'll happily use the terms in there. But when I'm just teaching students about the basics of C (and it appears chronodekar is at that level), I'll use terms that make more sense. – paxdiablo Nov 25 '09 at 08:54
  • 6
    Most of the confusion here stems from the "inventors of their own terms". No, you don't get to invent your own terms here. If you still want to, you'll have to choose the "unused" words for your own terms and you will have to provide precise definitions for these terms. As for the already-standardized terms: again, no, you will not [re-]invent them, regardless of how much you want to. And "visibility" and "scope" are already taken, sorry. – AnT stands with Russia Nov 25 '09 at 09:01
  • 2
    ... Which is especially important when it comes to those who just begin to learn the language. There's no greater disservice to them than to "plant" the incorrect self-invented definitions of universally accepted terms into their heads. – AnT stands with Russia Nov 25 '09 at 09:07
  • 2
    What an absolute crock. Do you really believe that all those terms in the standard make things *clearer* for a newbie? Talk of static storage duration and external linkage is not going to help them out at this point. Fine, once they learn the language well, they can look into the esoteric bits, but not when they're just starting. Again, if I'm talking to a "language lawyer" or someone that knows the standard very well, I'm happy using the real terms. But I'm not doing any learner a disservice by explaining the basic concepts in a more understandable way. You need to decide your audience. – paxdiablo Nov 25 '09 at 09:08
  • 1
    I'm talking about the term "visibility". This is the term you were trying to hijack. The term "visibility", as defined in the standard, has absolutely natural and very useful meaning. There's absolutely nothing unclear about it. By hijacking and redefining this term to something *completely unrelated* you are only creating confusion, not clearing it up. – AnT stands with Russia Nov 25 '09 at 09:12
  • It's your right to complain if you want @Andrey. But I'll still target my audience with appropriate terms. If you're a compiler writer or someone examining esoteric stuff like "are the aplha characters contiguous codepoints?" then, by all means look at the standard. If you just want to know how static works, you don't need to - there are simpler ways to explain it. I'm probably not going to convince you and I'm very certain you won't change my mind, so it's probably best to leave it there. – paxdiablo Nov 25 '09 at 09:56
7

You are misusing the term "scope". static in C has absolutely nothing to do with scope.

Scope is the region where the name of an entity (variable, function, typename etc.) is visible. In C language "file scope" is the largest scope ever. For that reason, there's no point in limiting anything to a single file: there's simply nothing larger to limit. There's no such thing as "global scope" in C. The term "global scope" is sometimes used informally, but in that case it has the same meaning as "file scope".

Again, static in C has absolutely nothing to do with scope. static in C affects storage duration of an object and linkage of an identifier. When used with objects (variables) static gives the object static storage duration (i.e. the object exists as long as the program runs). And, when used with identifiers of non-local objects or functions, it gives them internal linkage, meaning that the same identifier refers to the same entity within a single translation unit (where the entity is defined), but not in other translation units.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • In the `C` programming language book (K&R) they say that one of the uses of static is to limit scope, which is rather confusing, because just before that they say that the largest scope is the file scope. What is your opinion on that? It has always puzzled me. – Alexander Cska Feb 08 '16 at 23:31
  • 'static' means 'not on the stack'. You can't really explain it well without explaining the function call stack. – PaulMurrayCbr Jul 01 '16 at 06:22
  • 1
    @PaulMurrayCbr: The language specification does not use the concept of "function call stack" or any other "stack" for that matter. So yes, it is possible to explain it without involving any "stacks". – AnT stands with Russia Jul 01 '16 at 07:04
4

static is also used within a function definition to define a variable which keeps its value between function calls. I found an example here. In contrast, variables which are created anew with each function call are called automatic.

  • I wouldn't call it "opposite". It is like saying that red is opposite of yellow. In C89/90 there were two storage durations: static and automatic, but there was no "opposition" between them. C language (C99) has three storage durations: static, automatic and allocated. Again, there's no "opposite" here. – AnT stands with Russia Nov 25 '09 at 09:18
  • I've altered the answer slightly. –  Nov 25 '09 at 09:29
3

An example to augment Kinopiko’s answer:

#include <stdio.h>

int foo() {
    static int foo = 0;
    return ++foo;
}

int main() {
    printf("%i\n", foo()); // 1
    printf("%i\n", foo()); // 2
}

This can be used for example to return a safe pointer to a local function variable. Or in Objective-C it’s sometimes used to guard against repeated class initialization:

- (void) initialize
{
    static BOOL initialized = NO;
    if (initialized)
        return;
    // …perform initialization…
    initialized = YES;
}
zoul
  • 102,279
  • 44
  • 260
  • 354
  • In the example you just gave, let me assume it's in a file called "foo.c". Now if I have another file "aaa.c" and I call the function foo() from it, will the static variable still keep it's value? (I mean, if I call foo() from aaa.c, it's the same as calling it from another compilation unit, right?) – chronodekar Nov 25 '09 at 08:25
  • @chronodekar: what hapenned when you tried? Yes, calling `foo()` from aaa.c is the same as calling it from foo.c: the "internal" variable gets updated and the updated value is returned. – pmg Nov 25 '09 at 09:08
1

You are correct, this is called "static linkage": The symbol declared as static is only available in the compilation unit where it is defined.

The other use of static would be inside a function:

void f() {
  static int counter = 0;
  counter++;
  // ...
}

In this case the variable is only initialized once and keeps it's value through different calls of that function, like it would be a global variable. In this example the counter variable counts the number of times the function was called.

sth
  • 222,467
  • 53
  • 283
  • 367
1

A variable may have three kinds of storage:

  1. In program's Static Area
  2. On stack (during function call)
  3. On Heap (when you allocate using new/malloc)

Global variables are always stored in static area. But to store a local variable in static area, you need the keyword static. As a static variable is not allocated on stack, you can access the variable on subsequent calls.
Also static keyword at global scope gives a variable internal linkage.Consequently the variable cannot be accessed from some other file using the extern qualifier.

sud03r
  • 19,109
  • 16
  • 77
  • 96
1

internal linkage vs external linkage by example

//file1.c

#include <stdio.h>
int glb_var=3;//global variable
int func();  //prototype of function
int main()
{
    func();
    func();
    func();
    return 0;
}

int func()
{
    static int counter=0;//static varible
    printf("val of counter=%d",counter);
    counter+=5;
    return 0;
}

when we will compile this program and run this program then os will load this program in memory.then below things will happened:

  1. glb_var identifier will be stored in initialized data segment.

  2. counter identifier will be stored in uninitialized data segment called ".bss".

  3. static variable initialized once and the values persists during function calls.because static variable is stored in data segment not in stack so static variable persist during function calls. So output of the program will be: 0 5 10

one important thing about static variable is that it has internal linkage.so we can access this variable to a particular file.In which they are defined (not in other file).

We can access global variable glb_var in other file by using extern keyword. for eg:

//file2.c

#include <stdio.h>
extern glb_var; //for declaration of this variable
int main()
{
    if(glb_var)
    {
        printf("glb_var=%d",glb_var);
    }
}

output: 3 this is called external linkage.