varias son respuestas que pruebas logicas las funciones funcion ejercicios ejemplos condiciones con combinacion anidadas anidada c gcc nested-function

son - Implementación de funciones anidadas



funcion si excel varias condiciones (1)

GCC usa algo llamado trampolín.

Información: http://gcc.gnu.org/onlinedocs/gccint/Trampolines.html

Un trampolín es una pieza de código que GCC crea en la pila para usar cuando necesita un puntero a una función anidada. En su código, el trampolín es necesario porque pasa g como parámetro a una llamada de función. Un trampolín inicializa algunos registros para que la función anidada pueda referirse a variables en la función externa, luego salta a la función anidada. Los trampolines son muy pequeños: "rebotas" de un trampolín y en el cuerpo de la función anidada.

El uso de funciones anidadas de esta manera requiere una pila ejecutable, que se desaconseja en estos días. Realmente no hay forma de evitarlo.

Disección de un trampolín:

Aquí hay un ejemplo de una función anidada en C extendida de GCC:

void func(int (*param)(int)); void outer(int x) { int nested(int y) { // If x is not used somewhere in here, // then the function will be "lifted" into // a normal, non-nested function. return x + y; } func(nested); }

Es muy simple para que podamos ver cómo funciona. Aquí está el ensamblaje resultante del outer , menos algunas cosas:

subq $40, %rsp movl $nested.1594, %edx movl %edi, (%rsp) leaq 4(%rsp), %rdi movw $-17599, 4(%rsp) movq %rsp, 8(%rdi) movl %edx, 2(%rdi) movw $-17847, 6(%rdi) movw $-183, 16(%rdi) movb $-29, 18(%rdi) call func addq $40, %rsp ret

Notarás que la mayoría de lo que hace es escribir registros y constantes en la pila. Podemos seguirnos y encontrar que en SP + 4 coloca un objeto de 19 bytes con los siguientes datos (en sintaxis de GAS):

.word -17599 .int $nested.1594 .word -17847 .quad %rsp .word -183 .byte -29

Esto es bastante fácil de ejecutar a través de un desensamblador. Supongamos que $nested.1594 es 0x01234567 y %rsp 0x0123456789abcdef es 0x0123456789abcdef . El desensamblaje resultante, provisto por objdump , es:

0: 41 bb 67 45 23 01 mov $0x1234567,%r11d 6: 49 ba ef cd ab 89 67 mov $0x123456789abcdef,%r10 d: 45 23 01 10: 49 ff e3 rex.WB jmpq *%r11

Entonces, el trampolín carga el puntero de pila de la función externa en %r10 y salta al cuerpo de la función anidada. El cuerpo de la función anidada se ve así:

movl (%r10), %eax addl %edi, %eax ret

Como puede ver, la función anidada usa %r10 para acceder a las variables de la función externa.

Por supuesto, es bastante tonto que el trampolín sea más grande que la función anidada en sí misma. Usted podría hacerlo mejor. Pero no mucha gente usa esta característica, y de esta manera, el trampolín puede permanecer del mismo tamaño (19 bytes) sin importar qué tan grande sea la función anidada.

Nota final: en la parte inferior de la asamblea, hay una directiva final:

.section .note.GNU-stack,"x",@progbits

Esto indica al vinculador que marque la pila como ejecutable.

Recientemente descubrí que gcc permite la definición de función anidada. En mi opinión, esta es una característica interesante, pero me pregunto cómo implementarla.

Si bien no es difícil implementar llamadas directas de funciones anidadas pasando un puntero de contexto como un argumento oculto, gcc también permite tomar un puntero a una función anidada y pasar este puntero a una función arbitraria que a su vez puede llamar al anidado función del contexto. Como la función que llama a la función anidada solo tiene el tipo de función anidada para llamar, obviamente no puede pasar un puntero de contexto.

Sé que otros lenguajes como Haskell que tienen una convención de llamadas más intrincada permiten la aplicación parcial para respaldar tales cosas, pero no veo forma de hacerlo en C. ¿Cómo es posible implementar esto?

Aquí hay un pequeño ejemplo de un caso que ilustra el problema:

int foo(int x,int(*f)(int,int(*)(void))) { int counter = 0; int g(void) { return counter++; } return f(x,g); }

Esta función llama a una función que llama a una función que devuelve un contador del contexto y lo incrementa al mismo tiempo.