¿Cuál es la diferencia entre el vacío en línea estático y el vacío?

Estoy trabajando en lenguaje C y modificando código previamente escrito por otra persona. Estoy luchando con algunas cosas y estoy tratando de entender lo más que pueda sobre lo que está pasando. Entonces, como decía mi pregunta, ¿cuál es la diferencia entre static inline void and 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 encontré.

Encontré una explicación de static eso me confunde:

El especificador estático significa que no se puede hacer referencia a la función desde otros archivos; es decir, el enlazador no exporta el nombre.

Al leer esto, asumo 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é es hacer referencia a una función?

A través de la misma web, explican funciones en línea y no entiendo que significa

La palabra clave __inline le dice al compilador que sustituya el código dentro de la definición de función para cada instancia de una llamada de función. Sin embargo, la sustitución ocurre solo a discreción del compilador. Por ejemplo, el compilador no inserta una función si se toma su dirección o si es demasiado grande para insertarla.

¿Eh?

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

Lo siguiente se encuentra en file1.c (usando nombres genéricos ya que no creo que importe)

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

Lo siguiente se encuentra en file2.c

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

preguntado el 12 de junio de 12 a las 15:06

6 Respuestas

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

inline es una pista para el compilador de que el código de la función debe generarse en línea en el lugar donde se llama, en lugar de generarse como una función separada a la que se bifurca. Esto normalmente se hace por razones de rendimiento. Para tratar con la cita de Microsoft:

el compilador no inserta una función si se toma su dirección o si es demasiado grande para insertarla.

Una función en línea no tiene dirección, ya que no existe como una entidad separada. Su código se entrelaza a la perfección con el código desde el que se llama. Entonces, si toma la dirección de una función (por ejemplo, para asignarla a un puntero), el compilador tiene que generarla como una función real y no puede alinearla.

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


Habiendo mirado su ejemplo de código, supongo que hay una definición separada de CGauss() en algún lugar, que está siendo llamado desde archivo1.c, mientras que archivo2.c está llamando a su propia versión privada. O eso, o archivo1.c is #includeIng. archivo2.c. Lo cual sería desagradable.

Respondido el 12 de junio de 12 a las 15:06

además, inline es necesario 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 conozco este detalle exactamente en C, imagino que será lo mismo ) - rubenvb

Bueno, supongo que estoy un poco confundido que @ Graham-Borland. Déjame mostrarte por qué: COMPLEX cNoiseSample; CGauss( &cMuestra de ruido, 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 formato deficiente en el cuadro de comentarios, no estaba seguro de cómo hacer esto.*/ - TZPike05

Es #incluirlo. Hay mucho de eso en este código. Tratando con probablemente 200-250 archivos fuente y la misma cantidad de archivos de encabezado (me encanta trabajar en el código de otras personas :)) Ni siquiera pensé en que la función #include es la razón por la que funciona. - TZPike05

RE POR QUÉ debería usar static: Como regla general, su código será mucho más fácil de mantener si hace un uso liberal de static. Le dice al mantenedor "usted es libre de cambiar esta función sin romper nada fuera de este archivo". Cualquier símbolo (función o variable) que no sea estático puede ser referenciado literalmente desde cualquier lugar. Si viene de un lenguaje OOP (C++, Java, etc.), piense en static funciones (o variables globales) como private y todo lo demás como public. Además, usando static Las funciones permiten una optimización del compilador más agresiva. - Brian MacFarland

Aunque la static-Las funciones no se pueden llamar directamente desde otras unidades de traducción, puede pasar un puntero de función, que apunta a un static función, a otra unidad de traducción y llamar a estas funciones desde allí. - 12431234123412341234123

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

inline es una optimización del compilador que acelera su código en ciertos casos. Cada vez que llama a una función, hay algunos gastos generales asociados con ella. Entonces, lo que el compilador puede hacer es deshacerse de la función por completo copiando y pegando (casi) el código en línea.

He aquí un ejemplo de 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 elegante, también puede incorporar la función dotproduct;)

Tenga en cuenta que inline La palabra clave es simplemente un empujón para que el compilador alinee ciertas funciones. Puede o no hacerlo en realidad dependiendo de su propio juicio.

Respondido el 12 de junio de 12 a las 15:06

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

La palabra clave estática

Definir una función C estática significa (como dicen los documentos) que solo se puede acceder a esta función desde el archivo fuente en el que está definida. El término 'referencia' en este sentido significa llamar a esta función o, por ejemplo, tomar un puntero de función hacia ella. .

En línea

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

foo:
   /* some machine code */
   ret

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

  call <foo>

en el código de máquina de la persona que llama, lo que significa nada más que "salta a foo, ejecuta lo que encuentres allí y cuando encuentres una instrucción ret, regresa a esta ubicación".

Por el contrario, 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 en línea tiene la ventaja de ahorrarle dos saltos (la llamada y el ret respectivo), lo que hace que su código se ejecute un poco más rápido. Como desventaja, su código se vuelve más grande, porque inserta el código de máquina en cada sitio de llamada en lugar de tener solo una copia de una función invocable. Es por eso que generalmente solo incluye funciones pequeñas en línea.

Además, no puede llevar punteros de función 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 inserción se deja para el compilador como una opción de optimización y mediante el uso de una palabra clave como en línea de C++, su directiva en línea, o atributo __ de GCC((en línea)), solo le da al compilador una pista de que vale la pena intentarlo aquí.

Respondido el 12 de junio de 12 a las 15:06

Me gustaría agregar a todo lo anterior, antes de leer lo anterior, es importante entender cómo funciona la programación c. Si simplemente escribe código abierto, como

Setup(){
    int MainVar
}

MyRoutine(){
   int myVar1;
   int myVar2;
   bool myVar3;
   // Do stuff with myVars
   MainVar = myVar1 - myVar2;
   myVar3 = true;
}

Entonces cualquiera puede acceder a MyRoutine.myVar1 directamente desde un segundo programa. Podrían cambiar el valor de myVar2, (1. si no está protegido, 2. si saben que está allí, 3. si saben lo que hace) antes de que se use en MyRoutine // Do stuff, cambiando así lo que programador original previsto.

Imagina que estás escribiendo un programa bancario y dejaste el código vulnerable para que alguien pudiera cambiar el valor del DEPÓSITO sin cambiar el RETIRO del otro banco en tu rutina. Alguien más podría venir y escribir un programa separado para alterar ese valor por 2 o 10, y crear dinero donde no existía. Pero si precede el código, la rutina, el método o las variables con STATIC, otro programa no podrá acceder a esos elementos, verlos y, lo que es más importante, modificarlos.

Puede usar Static en cualquier punto, haciendo que las rutinas estén CERRADAS o las variables individuales solo CERRADAS. Permitiendo así que otros realicen cambios en ciertos aspectos de su código, pero conservando aquellos aspectos que deben protegerse.

Poner Static en MyRoutine evitaría que alguien ejecute MyRoutine desde otro programa. Dado que MyVars se declaran dentro de MyRoutine, no serían accesibles desde otro programa. Pero si hubiera una variable llamada MainVar declarada en otro lugar dentro del programa, sería accesible.

Setup(){
    int MainVar  // This can be accessed from outside this code
}

static MyRoutine(){  // Because of static these vars are not
   int myVar1;
   int myVar2;
   bool myVar3;
   // Do stuff with myVars
   MainVar = myVar1 - myVar2;
   myVar3 = true;
}

Y aquí, solo las variables con estática están protegidas. myVar3 podría leerse desde otro lugar informando a otra rutina que el intercambio se ha completado.

Setup(){
    int MainVar    // This can be accessed from outside this code
}

MyRoutine(){
   static int myVar1;  // This can NOT be accessed from outside this code
   static int myVar2;  // This can NOT be accessed from outside this code
   bool myVar3;        // This can be accessed from outside this code
   // Do stuff with myVars
   MainVar = myVar1 - myVar2;
   myVar3 = true;
}

contestado el 20 de mayo de 18 a las 21:05

static solo significa que esencialmente la función es, para todos los efectos, 'invisible' fuera del archivo fuente en el que está definida.

inline le pide al compilador que esencialmente sustituya el código de llamada de función directamente en la fuente en cada lugar donde 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 se garantiza 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.

Respondido el 12 de junio de 12 a las 20:06

Es muy simple

void* puede devolver un puntero vacío (cualquier referencia). Pero void no se puede devolver nada.

Por ejemplo:

1)

int x=7;

void *abc()    
{    
    return &x;    
}     

int main()    
{    
    printf("%d\n",*((int*)(abc())));    
}

Salida: 7

2)

int x=7;

void abc()    
{    
    return &x;    
}

int main()    
{    
    printf("%d\n",*((int*)(abc())));    
}

Producirá un error de compilación en printf("%d\n",*((int*)(abc())));

Porque void no puedo devolver nada.

Respondido el 20 de junio de 20 a las 10:06

Reemplace "printf("%d\n",((int)(abc())));" a "printf("%d\n",*((int)(abc())));", Es un error tipográfico - pawanesh kumar amigo

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.