Disponible la nueva versión "donationware" 7.3 de OrganiZATOR
Descubre un nuevo concepto en el manejo de la información.
La mejor ayuda para sobrevivir en la moderna jungla de datos la tienes aquí.

Curso C++

[Home]  [Inicio]  [Índice]


4.4.1b  Especificadores opcionales

§1  Sinopsis

Aunque no se trata de características estándar del lenguaje, incluimos aquí algunas particularidades relativas al compilador MS Visual C++, que (por compatibilidad) también existen en el homólogo de Borland [1].

§2  __declspec( )

Se trata de una palabra clave ( 3.2.1), específica de los mencionados compiladores , que es además un especificador de tipo de almacenamiento aplicable a la declaración de funciones y variables. Por ejemplo, en la declaración de clases.

Sintaxis

__declspec( <modificador> )

Ejemplo

class __declspec(dllimport) X { };
extern "C" __declspec(dllexport) double funcion();


Comentario

  <modificador> puede ser alguno de los siguientes:

dllexport

Sintaxis:

 __declspec( dllexport ) declarador

Este atributo define la interface entre una función, variable, u objeto de una librería de enlazado dinámico .DLL ( 1.4.4b2a) y su cliente.  Permitiendo que los objetos definidos con él, sean exportables desde la librería, haciéndolos accesibles desde un ejecutable o desde otra librería.

La declaración de funciones con este atributo elimina la necesidad de declarar un fichero de definición (.DEF) del módulo que contiene a la función.  Al menos en lo relativo a la especificación de funciones exportables.  Ver ejemplo ( 1.4.4b2a).

Nota: dllexport reemplaza a la palabra clave __export.

dllimport

Sintaxis:

__declspec( dllimport ) declarador

Este atributo permite importar funciones, datos u objetos situados en una librería de enlace dinámico (DLL) desde otro ejecutable ( 1.4.4b2b). Ver ejemplo ( 1.4.4b2a).

Nota: dllimport reemplaza la palabra clave __import.

naked

Sintaxis:

__declspec( naked ) declarator

El atributo naked es aplicable solo a la definición de una función, y no supone un modificador de tipo.  Su utilización origina la supresión del código de prólogo y epílogo (de ahí su nombre de funciones "desnudas").  Lo que causa a su vez que al ser invocada la función no se construya marco de pila de forma estándar.  La función no preserva los valores de los registros como es usual, y es responsabilidad del programador conformar las convenciones que necesite el invocador de la función.

Esta posibilidad suele utilizarse junto con código de prólogo y epílogo de cosecha propia en ensamblador ().  Las funciones desnudas son especialmente adecuadas cuando hay que escribir manejadores de dispositivos virtuales ("Virtual device drivers").

Ejemplo:

__declspec( naked ) int funcion( parametros-formales ) {
  // cuerpo de la función
}

noreturn

Sintaxis:

__declspec( noreturn ) declarador

Este atributo se utiliza para informar al compilador que una función no tiene retorno. Como consecuencia, el compilador es informado que el código que siga a la invocación de dicha función no puede ser ejecutado.

La justificación de este atributo hay que buscarlo en que el compilador dispone de un mecanismo controlador de la senda de ejecución. Este mecanismo genera un mensaje de aviso ("Warning" 1.4) si descubre una función que no devuelve el valor esperado. En estos casos, si la senda de ejecución no sigue su camino normal debido a que se interpone una función que no tiene retorno, puede utilizarse este atributo para prevenir la aparición del error. Además, en caso que pueda asegurarse que la función no tendrá retorno el compilador puede generar un código ligeramente más eficiente.

El Estándar define dos funciones que no tienen retorno, son las funciones abort ( 1.5.1) y exit ( 1.5.1)

Ejemplo:  considere el código siguiente en el que la segunda cláusula else no contiene una sentencia return y la declaración de func1 como noreturn (sin retorno) para prevenir el error.

__declspec( noreturn ) extern void func1 () {
  ...
}

int func2() {
  if(...) return 1;
  else if(...) return 0;
  else func1();    // no hay retorno
}

Nota: este especificador noreturn no está recogido en el Estándar Ansi C++.  Aunque los compiladores Borland;  GNU cpp y MS Visual C++ lo utilizan.

nothrow

Sintaxis:

__declspec( nothrow ) declarador

Este atributo se utiliza exclusivamente en la declaración de funciones, y sirve para informar al compilador que la función así declarada, y las que puedan ser invocadas por ella, no lanzan nunca una excepción ( 1.6).

Ejemplo:  las tres declaraciones que siguen son equivalentes:

#define WINAPI __declspec(nothrow) __stdcall

void WINAPI func1();                         // F1
void __declspec(nothrow) __stdcall func2();  // F2
void __stdcall func3() throw();              // F3

Las formas F1 y F2 presentan la ventaja de que puede utilizarse una definición de la API (de Windows) con la que puede especificarse fácilmente la característica nothrow para una serie de funciones.  Por su parte F3 es la forma "canónica" de C++ ( 1.6.4).

novtable

Sintaxis:

__declspec( novtable ) declarador

Este especificador solo es aplicable a la declaración de clases, aunque solo es aplicable a clases que sean pura interfaz ( 4.11.8c).

En realidad la labor de este especificador consiste en informar al compilador que en la definición de constructores y destructores no genere el código necesario para inicializar el puntero a la tabla de funciones virtuales (vfptr 4.11.8a).  En muchos casos solo existe una referencia asociada a la vtable ( 4.11.5) de la clase, por lo que el enlazador puede eliminarla, lo que se traduce en una significativa reducción del código.

property
selectany

Sintaxis:

__declspec( selectany ) declarador

Los datos globales ( 4.1.3) solo pueden ser inicializados una vez en cualquier ejecutable EXE o DLL ( 4.1.2).  Este atributo puede ser usado para inicializar datos globales definidos en los ficheros de cabecera cuando la referida cabecera aparece en más de un fuente.

Nota: este atributo solo puede usarse en la inicialización de datos globales que sean visibles externamente.

thread
uuid

  Inicio.


[1]  Creemos que la abrumadora preponderancia de la plataforma Wintel en el panorama de la informática actual, hace innecesaria cualquier justificación respecto a la importancia de estas "particularidades".