2012-01-23 21 views
11

No estoy seguro de si es realmente necesario tener prototipos para funciones estáticas en C. Siempre que no esté exportando tales funciones (es decir, que no tengan enlaces externos), ¿Qué otro beneficio puede dar esto?prototipos para funciones "estáticas"

Gracias.

Respuesta

6

E.g. si necesita asegurarse de que una función tenga un cierto tipo, puede ser útil.

Considera:

// Define how the functions should be defined. 
typedef void * jobfunc(void *); 

// Use case 
void addjob(jobfunc *); 

// Ensure they have the right type. Without this, you only get a warning 
// for addjob(job2) (see below) - with it, you get an error for the mismatch. 
static jobfunc job1; 
static jobfunc job2; 

// Define one job 
static void * job1(void * arg) { 
    return NULL; 
} 

// Define another job - accidentally wrong. 
static void * job2(int accidentally_wrong) { 
    return NULL; 
} 
+3

Creo que usar typedef como una especie de plantilla de función es una práctica bastante oscura, lo más probable es que simplemente confunda al lector. Por ejemplo, me tomó un tiempo interpretar lo que realmente hace tu código. Mi reacción inmediata pero incorrecta al código fue "aha - punteros a la función". – Lundin

+0

@Lundin Tienes razón en cuanto a que es inusual. Pero hace su trabajo. Tal vez el tipo de retorno 'void *' haya agregado confusión; como ejemplo, debería haber tomado un tipo diferente. Sin embargo, no entiendo por qué es tan inusual, es genial para garantizar el tipo correcto y, aparte de la legibilidad y la confusión debido a la desconocida, no veo una desventaja. – glglgl

6

Si desea utilizarlos antes de la implementación, debe escribir un prototipo.

Normalmente, puede cambiar el orden de las funciones, pero ¿qué ocurre si tiene 2 funciones estáticas que se llaman entre sí?

+0

@Mark: Por ejemplo, el compilador necesita saber cuál es la firma de la función 'foo' antes de analizar una llamada a la función' foo', para asegurarse de que la llamada a 'foo' presione los parámetros correctos y tal . –

+0

asaelr: ¿podría dar más detalles sobre su comentario? ¿A qué te refieres con 'usar antes de la implementación'? – Mark

+0

como escribió ouah, quiero decir que puede escribir una función de llamada arriba de la función llamada. – asaelr

3

Una conveniencia (menor) es que le permitirá colocar las funciones en cualquier lugar que desee en el archivo. Por ejemplo, si desea colocar sus funciones de utilidad al final del archivo, debe declararlas.

Un caso en el que debe declarar sus funciones es cuando tiene dos funciones recursivas recíprocas, ya que la primera situada en el archivo aún no ha visto la otra función.

4

Una declaración sin una definición de función static (esto es lo mismo para una función extern) le permite llamar a la función antes de que se defina la función. En C, un identificador para una función tiene que ser declarado antes de que pueda ser utilizado:

static void foo(void); 

void bar(void) 
{ 
    foo(); 
} 

static void foo(void) 
{ 
    ... 
} 
+0

¡Muchas gracias a todos por sus respuestas exhaustivas! – Mark

8

Para citar alguna autoridad, Misra-C: 2004 regla 8.1 hace cumplir prototipos para las funciones con enlace externo, pero también menciona enlace interno :

"La provisión de un prototipo para una función con enlace interno es buena práctica de programación."

Supongo que es una buena práctica porque hace que su estilo de codificación entre las funciones de vinculación interal/externa sea consistente. Y como otros han mencionado en sus respuestas, también es conveniente.

+1

Esta es una de las pocas reglas de MISRA que acepto. Siempre pongo (en la parte superior del archivo fuente) las declaraciones de la función 'estática' de todas las funciones' estáticas' que están definidas en un archivo fuente. Esta es una buena documentación del código y de la API interna. – ouah

0

Si no va a declarar el prototipo de la función del código de abajo será válida.

static int bar() 
{ 

}; 

int foo() 
{ 
    bar("asdf"); 
}; 

Y este tipo de errores ocultos pueden ser peligrosos. Revisar la sección "2 7 .2.2 Verificación de tipo de argumento de función" de nuevo podría ser útil Principios y práctica con C++ [Bjarne Stroustrup].

Cuestiones relacionadas