stringtranslate.com

Bloques (extensión de lenguaje C)

Los bloques son una extensión no estándar agregada por Apple Inc. a las implementaciones de Clang de los lenguajes de programación C , C++ y Objective-C que utiliza una sintaxis similar a una expresión lambda para crear cierres dentro de estos lenguajes. Los bloques son compatibles con programas desarrollados para Mac OS X 10.6+ y iOS 4.0+, [1] aunque los tiempos de ejecución de terceros permiten su uso en Mac OS X 10.5 y iOS 2.2+ [2] y sistemas que no sean Apple.

Apple diseñó bloques con el objetivo explícito de facilitar la escritura de programas para la arquitectura de subprocesos de Grand Central Dispatch , [3] [4] aunque es independiente de esa arquitectura y puede usarse de manera muy similar a los cierres en otros lenguajes. Apple ha implementado bloques tanto en su propia rama de GNU Compiler Collection [1] como en la interfaz del compilador Clang LLVM . La compatibilidad con la biblioteca de lenguaje de ejecución para bloques también está disponible como parte del proyecto LLVM. El grupo Khronos utiliza la sintaxis de bloques para poner en cola los núcleos desde dentro de los núcleos a partir de la versión 2.0 de OpenCL . [5]

Al igual que las definiciones de funciones, los bloques pueden tomar argumentos y declarar sus propias variables internamente. A diferencia de las definiciones de funciones C ordinarias, su valor puede capturar el estado del contexto circundante. Una definición de bloque produce un valor opaco que contiene una referencia al código dentro del bloque y una instantánea del estado actual de las variables de la pila local en el momento de su definición. Posteriormente, el bloque se puede invocar de la misma manera que un puntero de función. El bloque puede asignarse a variables, pasarse a funciones y, de lo contrario, tratarse como un puntero de función normal, aunque el programador de la aplicación (o la API) debe marcar el bloque con un operador especial (Block_copy) si se va a utilizar fuera del alcance en que fue definido.

Dado un valor de bloque, el código dentro del bloque se puede ejecutar en cualquier momento posterior llamándolo, usando la misma sintaxis que se usaría para llamar a una función.

Ejemplos

Un ejemplo simple que captura un estado mutable en el ámbito circundante es un iterador de rango entero : [6]

/* blocks-test.c */ #include <stdio.h> #include <Block.h> /* Tipo de bloque que no toma nada y devuelve un int */ typedef int ( ^ IntBlock )();    IntBlock MakeCounter ( int inicio , int incremento ) { __block int i = inicio ; return Block_copy ( ^ ( void ) { int ret = i ; i += incremento ; return ret ; }); }                  int main ( void ) { IntBlock micontador = MakeCounter ( 5 , 2 ); printf ( "Primera llamada: %d \n " , micontador ()); printf ( "Segunda llamada: %d \n " , micontador ()); printf ( "Tercera llamada: %d \n " , micontador ()); /* debido a que fue copiado, también debe liberarse */ Block_release ( mycounter ); devolver 0 ; }          

Compilar y ejecutar

$ clang  -fblocks  blocks-test.c # Mac OS X $ ./a.out Primera llamada: 5 Segunda llamada: 7 Tercera llamada: 9 

El tiempo de ejecución de los bloques no forma parte de las bibliotecas C vinculadas de forma predeterminada en algunos sistemas. Si este es el caso, es necesario vincular explícitamente a esta biblioteca:

$ clang  -fblocks  bloques-test.c  -lBlocksRuntime # Linux 

El tiempo de ejecución es parte del tiempo de ejecución de clang, pero a veces no se instala con el paquete clang. Está disponible un tiempo de ejecución independiente extraído de compilador-rt. [7]

Relación con las funciones anidadas de GCC

Los bloques tienen un parecido superficial con la extensión de C de GCC para soportar funciones anidadas de ámbito léxico . [8] Sin embargo, las funciones anidadas de GCC, a diferencia de los bloques, no deben llamarse después de que el alcance que las contiene haya salido, ya que eso daría como resultado un comportamiento indefinido .

Las funciones anidadas de estilo GCC actualmente utilizan la creación dinámica de procesadores ejecutables en la mayoría de las arquitecturas al tomar la dirección de la función anidada. En la mayoría de las arquitecturas (incluida X86), estos procesadores se crean en la pila, lo que requiere marcar la pila como ejecutable. Las pilas ejecutables generalmente se consideran un potencial agujero de seguridad. Los bloques no requieren el uso de procesadores ejecutables, por lo que no comparten esta debilidad. Por otro lado, los bloques introducen un tipo completamente nuevo de puntero, mientras que los punteros a funciones anidadas en GCC son punteros de funciones normales y se pueden usar directamente con el código existente.

Ver también

Referencias

  1. ^ ab "Temas de programación de bloques". Desarrollador de Apple . Apple Inc . Consultado el 8 de marzo de 2011 .
  2. ^ "Google Code Archive: almacenamiento a largo plazo para el alojamiento de proyectos de Google Code".
  3. ^ "Grand Central Dispatch" (PDF) (resumen tecnológico). Manzana . 2009-09-03. Archivado desde el original (PDF) el 20 de septiembre de 2009 . Consultado el 9 de junio de 2009 .
  4. ^ Siracusa, John (1 de septiembre de 2009). "Mac OS X 10.6 Snow Leopard: la revisión de Ars Technica: bloques". Ars Técnica .
  5. ^ Munshi, Aaftab, ed. (13 de julio de 2013). "La especificación OpenCL C. Versión 2.0. Revisión del documento 11" (PDF) . Grupo de trabajo Khronos OpenCL. pag. 173. Archivado desde el original (PDF) el 5 de noviembre de 2013 . Consultado el 23 de julio de 2013 .
  6. ^ Bengtsson, Joaquín. "Programación con bloques C en dispositivos Apple". Archivado desde el original el 15 de noviembre de 2017 . Consultado el 17 de septiembre de 2009 .
  7. ^ "mackyle/blocksruntime: tiempo de ejecución de bloques independientes" . Consultado el 15 de enero de 2020 .
  8. ^ "Funciones anidadas: uso de la colección de compiladores GNU (GCC)".

enlaces externos