2010-01-29 3 views
6

Estoy tratando de comprender el comportamiento exacto de los especificadores de clase de almacenamiento en C99, y algunos comportamientos de GCC parecen no seguir la especificación, a menos que malinterprete la especificación. De 6.2.2 (2):Vinculación en C: ¿GCC sigue las especificaciones C99, o no entiendo la especificación?

Dentro de una unidad de traducción, cada declaración de un identificador con enlace interno denota el mismo objeto o función.

Sin embargo, he probado GCC (PowerPC-apple-darwin9-gcc-4.2.1) con el siguiente programa:

#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; 
} 

Compilado con -std=c99, imprime el siguiente:

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

Si entiendo la especificación correctamente, debería imprimir:

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

Entiendo por qué GCC se desviaría de las especificaciones aquí, solo me pregunto si hay una explicación más profunda para este comportamiento.

Respuesta

9

el párrafo siguiente, 6.2.2/3, es importante:

Si la declaración de un identificador de alcance archivo para un objeto o una función contiene el especificador de clase de almacenamiento estático, el identificador tiene enlace interno.

(tenga en cuenta el hecho hincapié identificador de ámbito archivo).

Sus variables estáticas x no tienen alcance de archivo, tienen alcance de bloque.

+0

En otras palabras, cada x es local para la función que lo declara. –

+0

Gracias. Es fácil perder palabras en la especificación. –

+2

@Dietrich: Lo es. De hecho, es tan fácil, me perdí la parte más relevante e importante, que se publicó como respuesta. –

10

En 6.2.2 (6) que dice:

Los siguientes identificadores tienen ninguna vinculación: [...] un ámbito de bloque identificador para un objeto declarado sin el extern especificador de clase de almacenamiento .

Las variables estáticas son identificadores de alcance de bloque para objetos, y no están declarados extern. Por lo tanto, no tienen ningún vínculo, especialmente el enlace interno.

+2

+1; eso es más relevante que el párrafo que cité. –

Cuestiones relacionadas