2009-12-22 24 views
6

Noté un comportamiento muy curioso que, si es estándar, me encantaría explotar (lo que me gustaría hacer con él es bastante complejo de explicar e irrelevante para la pregunta).Declarar una función estática y luego no estática: ¿es estándar?

El comportamiento es:

static void name(); 
void name() { 
    /* This function is now static, even if in the declaration 
    * there is no static keyword. Tested on GCC and VS. */ 
} 

Lo curioso es que la inversa produce un error de compilación tiempo:

void name(); 
static void name() { 
    /* Illegal */ 
} 

Por lo tanto, es esta norma y puedo esperar otros compiladores a comportarse de la misma manera ? ¡Gracias!

Respuesta

12

C++ estándar:

7.1.1/6: "A name declared in a namespace scope without a storage-class-specifier has external linkage unless it has internal linkage because of a previous declaration" [or unless it's const].

En el primer caso, name se declara en un ámbito de espacio de nombres (en concreto, el espacio de nombres global). La primera declaración por lo tanto altera el vínculo de la segunda declaración.

La inversa está prohibida porque:

7.1.1/7: "The linkages implied by successive declarations for a given entity shall agree".

Por lo tanto, en su segundo ejemplo, la primera declaración tiene enlazado externo (por 7.1.1/6), y el segundo tiene enlace interno (explícitamente), y estos no están de acuerdo.

También preguntas sobre C, y me imagino que es el mismo tipo de cosas. Pero tengo el libro de C++ aquí, mientras que usted es tan capaz de buscar en un borrador C estándar en línea como yo ;-)

+0

Estoy usando C++, pero agregué una etiqueta C porque pensé que sería lo mismo en C. –

+0

oh y gracias por la gran respuesta –

3

Los calificadores que coloca en el prototipo de función (o que están implícitos) se usan automáticamente cuando la función es declarada.

Por lo tanto, en su segundo caso, la falta de static en el prototipo significaba que la función se definió como NO estática, y luego cuando se declaró como estática, fue un error.

Si dejara el tipo de devolución en el prototipo, el valor predeterminado sería int y luego obtendría un error nuevamente con el tipo de devolución void. Lo mismo sucede con __crtapi y __stdcall y __declspec() (en el compilador de Microsoft C).

Cuestiones relacionadas