tags:

views:

161

answers:

2

I'm trying to understand the exact behavior of storage class specifiers in C99, and some GCC behavior seems not to follow the spec, unless I misunderstand the spec. From 6.2.2 (2):

Within one translation unit, each declaration of an identifier with internal linkage denotes the same object or function.

However, I tested GCC (powerpc-apple-darwin9-gcc-4.2.1) with the following program:

#include <stdio.h>
static int f() {
    static int x = 0;
    return x++;
}
static int g() {
    static int x = 0;
    return x++;
}
int main(int argc, char *argv[]) {
    printf("g() = %i\n", g());
    printf("g() = %i\n", g());
    printf("f() = %i\n", f());
    printf("f() = %i\n", f());
    return 0;
}

Compiled with -std=c99, It prints the following:

g() = 0
g() = 1
f() = 0
f() = 1

If I understand the spec correctly, it should print:

g() = 0
g() = 1
f() = 2
f() = 3

I understand why GCC would deviate from the spec here, I'm just wondering if there's a deeper explanation for this behavior.

+7  A: 

The next paragraph, 6.2.2/3, is important:

If the declaration of a file scope identifier for an object or a function contains the storage-class specifier static, the identifier has internal linkage.

(note the emphasized file scope identifier).

Your static variables x do not have file scope, they have block scope.

James McNellis
In other words, each x is local to the function that declares it.
Richard Pennington
Thanks. It's easy to miss words in the spec.
Dietrich Epp
@Dietrich: It is. In fact, it's so easy, I missed the more relevant and important part, which sth posted as an answer.
James McNellis
+6  A: 

In 6.2.2 (6) it says:

The following identifiers have no linkage: [...] a block scope identifier for an object declared without the storage-class specifier extern.

The static variables are block scope identifiers for objects, and they are not declared extern. Therefore they have no linkage, especially not internal linkage.

sth
+1; that's more relevant than the paragraph I cited.
James McNellis