ptr pointer functions examples c function function-pointers

pointer - ¿Cómo implementar una función “privada/restringida” en C?



ptr function c (6)

Me hicieron una pregunta muy interesante durante una entrevista en C: ¿Cómo puede implementar una función f () de tal manera que solo pueda llamarse desde una función g () en particular? Si una función que no sea g () intenta llamar a f (), se generará un error de compilación.

Al principio, pensé que esto podría hacerse con punteros de función y podría acercarme a bloquear la llamada en tiempo de ejecución. Pero no pude pensar en una estrategia de compilación. Ni siquiera sé si esto es posible usando ANSI C.

¿Alguien tiene alguna idea?


Aquí hay una forma:

int f_real_name(void) { ... } #define f f_real_name int g(void) { // call f() } #undef f // calling f() now won''t work

Otra forma, si puede garantizar que f() g() son las únicas funciones en el archivo, es declarar f() como static .

EDITAR: Otro truco macro para causar errores del compilador:

static int f(void) // static works for other files { ... } int g(void) { // call f() } #define f call function // f() certainly produces compiler errors here


Coloque f() g() en el mismo archivo fuente, declare f() estático.


Coloque g () yf () en el mismo módulo, y declare f () como estático. La palabra clave estática hace que f () esté disponible solo para funciones en el mismo módulo o archivo fuente.

Es posible que también desee mencionar que no se deben permitir otros métodos en el módulo con f () yg (), de lo contrario podrían llamar a f ().

PD: Realmente creo que la respuesta de Chris Lutz es en realidad la mejor. Menciona este enfoque, pero también un ingenioso cambio de nombre de macro que funciona con menos condiciones ambientales (no requiere el archivo de módulo específicamente para estas dos funciones).

Tenga en cuenta también que con una macro, podría hacer lo siguiente:

#define f() f_should_not_be_called_by_anything_except_g

Lo que presentaría un buen mensaje de error, y los completadores automáticos (como Visual Studio) mostrarían esa sugerencia cuando el usuario escriba f ().


Puedes hacer funciones de módulo privado con la palabra clave static :

static void func(void) { // ... }

Entonces, func() solo puede ser llamado por otras funciones definidas en el mismo archivo (técnicamente, la misma unidad de traducción : otras funciones cuyas definiciones están incluidas por una directiva #include todavía pueden acceder a ella). Se dice que la función tiene un enlace interno . Se dice que todas las demás funciones (es decir, sin la palabra clave static ) tienen un enlace externo .

Más allá de eso, no, no hay manera de hacer que las funciones sean inaccesibles. Puede usar macros para cambiar el nombre de la función, pero otro código siempre puede acceder a ella con el nombre apropiado.


Sólo es posible casualmente.

Si las funciones f () y g () están en el mismo archivo de origen, y no hay otras funciones en el archivo, y si g () nunca devuelve el puntero a f () a ninguna de sus personas que llaman, entonces f () static hará el trabajo.

Si otras funciones deben aparecer en el mismo archivo de origen, coloque f () en la parte inferior del archivo como una función estática, y solo definiendo g () inmediatamente después de que lograría más o menos el mismo efecto, aunque si no lo hiciera Dígale al compilador que genere errores en las ''declaraciones faltantes'', otras funciones podrían llamarlo con advertencias.

#include <stdio.h> extern void g(void); /* in a header */ /* Other functions that may not call f() go here */ static void f(void) { puts("X"); } void g(void) { f(); }

Claramente, esta técnica no se puede extender de manera confiable a otro par de funciones en el mismo archivo, x () e y (), de modo que x () y solo x () pueden llamar a y () mientras que g () y solo g () Puede llamar f () al mismo tiempo.

Sin embargo, normalmente confiaría en la disciplina de los programadores y simplemente haría f () estática en el archivo fuente, junto con un comentario que solo g () puede llamar, y luego disciplinar a cualquiera que modifique el código para que una función que no sea g () llama a f ().


Una opción para GCC es usar funciones anidadas . Si bien no es estándar C, funciona bastante bien.