2012-06-12 13 views
13

Estoy trabajando en el lenguaje C y modificando el código previamente escrito por otra persona. Estoy luchando con algunas cosas y trato de entender todo lo que pueda sobre lo que está sucediendo como puedo. Entonces, como decía mi pregunta, ¿cuál es la diferencia entre static inline void y void al crear una función? Me disculpo de antemano por la publicación larga, pero quería que supieras que investigué un poco, pero no entiendo lo que he encontrado.¿Cuál es la diferencia entre el vacío estático en línea y el vacío?

He encontrado an explanation of static que me confunde:

El especificador estática significa que la función no se puede hacer referencia de otros archivos; es decir, el nombre no es exportado por el vinculador.

Al leer esto, supongo que hacer referencia a una función es diferente a llamar a una función? Supongo que porque esta función se llama desde otro archivo .c. Si ese es el caso, ¿qué hace referencia a una función?

A través del mismo sitio web, explican inline functions y no entiendo lo que significa.

La palabra clave __inline le dice al compilador para sustituir el código dentro de la definición de la función de cada caso de una llamada de función. Sin embargo, la sustitución solo ocurre a discreción del compilador. Para el ejemplo , el compilador no alinea una función si su dirección es tomada o si es demasiado grande para alinearse.

Huh ???

Cualquier ayuda es muy apreciada, y una vez más me disculpo por la publicación terriblemente larga.

La siguiente se encuentra en Archivo1.c (El uso de nombres genéricos, ya que no creo que importe)

COMPLEX cNoiseSample; 
CGauss(&cNoiseSample, loopbackRadio->pState); 

La siguiente se encuentra en Archivo2.c

static inline void CGauss(COMPLEX * pcGauss, P_OS_UNIFORM_RAND_STATE pState) 
{ 
    //code 
} 

Respuesta

12

static significa que no se puede hacer referencia a ella desde otra unidad de compilación (archivo fuente). "Referenciado" significa llamado, o referido por su nombre, por ej. asignado a un puntero de función.

inline es una sugerencia para el compilador que el código de la función debe ser generado en línea en el lugar que se llama, en lugar de generarse como una función separada para ser ramificado a. Esto normalmente se hace por motivos de rendimiento. Para hacer frente a la cita de Microsoft:

el compilador no coloca en línea de la función si se toma su dirección o si es demasiado grande para en línea.

Una función en línea no tiene dirección, ya que no existe como una entidad separada. Su código está entrelazado sin problemas con el código desde el que se llama. Por lo tanto, si toma la dirección de una función (por ejemplo, para asignarla a un puntero), el compilador debe generarla como una función real y no puede insertarla en línea.

void significa que la función no devuelve un valor.


Después de haber analizado su ejemplo de código, supongo que no hay una definición separada de CGauss() algún lugar, que está siendo llamado desde Archivo1.c, mientras que Archivo2.c está llamando a su propio privada versión. O eso, o file1.c es #include ing file2.c. Lo cual sería desagradable.

+0

también, 'inline' es necesario para hacer cumplir la regla de una definición cuando una función se define en un encabezado incluido en diferentes unidades de compilación (o al menos este es el caso de C++, no se conoce exactamente este detalle en C, I imagina que será lo mismo) – rubenvb

+0

Bueno, supongo que estoy un poco confundido que @ Graham-Borland. Déjame mostrarte por qué: COMPLEX cNoiseSample; CGauss (& cNoiseSample, loopbackRadio-> pState);/* Este código se llama en un punto en un archivo fuente .c, y en un archivo fuente .c diferente, tengo esto: */static inline void CGauss (COMPLEX * pcGauss, P_OS_UNIFORM_RAND_STATE pState)/* Me disculpo por el pobre formato en el cuadro de comentarios, no estaba seguro de qué otra manera hacer esto. */ – TZPike05

+0

Edite su pregunta, pegue ese fragmento de código allí. –

6

static solo significa algo cuando tiene más de un archivo fuente. Especifica que no se puede acceder a la función o variable static desde funciones en un archivo diferente.

inline es una optimización del compilador que acelera su código en ciertos casos. Cada vez que llamas a una función, hay una sobrecarga asociada a ella. Entonces, lo que el compilador puede hacer es deshacerse de la función todo junto copiando y pegando (casi) el código en línea.

He aquí un ejemplo de procesos en línea:

int dotproduct(int x1, int y1, int x2, int y2) { 
    return multiply(x1,x2)+multiply(y1,y2); 
} 

inline int multiply(int a, int b) { 
    return a*b; 
} 

el compilador convertir esto en:

int dotproduct(int x1, int y1, int x2, int y2) { 
    return x1*x2+y1*y2; 
} 

Si quiere ser de lujo, también puede inline la función dotProduct;)

Tenga en cuenta que la palabra clave inline es simplemente un empujoncito al compilador para que incorpore ciertas funciones. Puede o no puede realmente hacerlo dependiendo de su propio juicio.

+0

Gracias @tskuzzy, en línea tiene mucho más sentido ahora. – TZPike05

0

estática sólo significa que, básicamente, la función es para todos los intentos y propósitos 'invisible' fuera del archivo de origen que se define en.

línea askes el compilador para substite esencialmente el código de llamada a la función directamente en la fuente en cada lugar se llama a la función en tiempo de compilación (como un reemplazo de la llamada de función con el código de la función); sin embargo, no está garantizado que suceda, simplemente lo sugiere a su compilador.

Es más técnico que eso y es probable que obtenga una respuesta mucho mejor, pero en un lenguaje simple, esto es lo que significan los términos.

2

La palabra clave static

Definir un medio estático de función C (como dicen los documentos) que esta función sólo se puede acceder desde el origen del archivo que se define en. El término 'referencia' en este medio SENCE llamando a esta función o tomando un puntero a ella.

Inlining

Normalmente, cuando se escribe una función en C, el compilador genera el código máquina para esta función:

foo: 
    /* some machine code */ 
    ret 

Cada vez que se llama a esta función, el compilador inserta una instrucción como

call <foo> 

en el código máquina de la persona que llama, lo que significa nada más que "saltar a foo, e xecute lo que encuentre allí y cuando encuentre una instrucción ret, regrese a esta ubicación ".

En cambio, para las funciones en línea, el compilador no genera una función separada foo(), sino que inserta el código de máquina para la función foo en cada sitio de llamada. Al ejecutar este código, esto tiene el mismo efecto.

Entonces, ¿por qué hacemos eso? El código de entrada tiene la ventaja de ahorrarte dos saltos (la llamada y el ret respectivo), lo que hace que tu código se ejecute un poco más rápido. Como inconveniente, su código se agranda porque inserta el código de máquina en cada sitio de llamadas en lugar de tener solo una copia de una función invocable. Es por eso que usualmente solo haces pequeñas funciones en línea.

Además, no puede tomar punteros a funciones en línea, y la depuración se vuelve más difícil, porque no puede establecer fácilmente un punto de interrupción en una función en línea.

Por lo tanto, la expansión en línea se deja para el compilador como una opción de optimización y mediante el uso de una palabra clave como línea C++ 's, su directiva en línea , o __attribute ((en línea)), sólo se da el compilador de una pista de GCC que inlining podría valer la pena intentarlo aquí.

Cuestiones relacionadas