Calificadores de tipos

Los calificadores de tipo proporcionan una de dos propiedades a un identificador. El calificador de tipo const declara que un objeto no es modificable. El calificador de tipo volatile declara un elemento cuyo valor se puede modificar legítimamente por algo que esté más allá del control del programa en el que aparece, por ejemplo, un subproceso que se ejecute en paralelo.

Los calificadores de tipo, const , restrict y volatile , solo pueden aparecer una vez en una declaración. Los calificadores de tipo pueden aparecer con cualquier especificador de tipo; sin embargo, no pueden aparecer después de la primera coma en una declaración de elementos múltiples. Por ejemplo, las siguientes declaraciones son válidas:

typedef volatile int VI;
const int ci;

Estas declaraciones no son válidas:

typedef int *i, volatile *vi;
float f, const cf;

Los calificadores de tipo solo son pertinentes al tener acceso a identificadores como valores L en expresiones. Vea Expresiones de valor L y de valor R para obtener información sobre valores L y expresiones.

Sintaxis

type-qualifier:
const
restrict
volatile

const y volatile

Las siguientes declaraciones const y volatile son válidas:

int const *p_ci;      // Pointer to constant int
int const (*p_ci);   // Pointer to constant int
int *const cp_i;     // Constant pointer to int
int (*const cp_i);   // Constant pointer to int
int volatile vint;     // Volatile integer

Si la especificación de un tipo de matriz incluye calificadores de tipo, se califica el elemento, no de tipo de matriz. Si la especificación de tipo de la función incluye calificadores, el comportamiento es indefinido. Ni volatile ni const afectan al intervalo de valores ni a las propiedades aritméticas del objeto.

  • La palabra clave const se puede usar para modificar cualquier tipo fundamental o agregado, un puntero a un objeto de cualquier tipo o typedef . Si un elemento se declara solo con el calificador de tipo const, se asume que su tipo es const int. Una variable const se puede inicializar o puede colocarse en un área de almacenamiento de solo lectura. La palabra clave const es útil para declarar punteros a const puesto que requiere que la función no cambie el puntero de ninguna manera.

  • El compilador supone que, en cualquier punto del programa, se puede tener acceso a una variable volatile mediante un proceso desconocido que utilice o modifique su valor. Con independencia de las optimizaciones especificadas en la línea de comandos, el código de cada asignación de una variable volatile , o de cada referencia a ella, debe generarse aunque no parezca tener ningún efecto.

Si solo se usa volatile, se supone int. El especificador de tipo volatile se puede utilizar para proporcionar acceso confiable a ubicaciones de memoria especiales. Use volatile con objetos de datos a los que se pueda tener acceso o que se puedan modificar mediante controladores de la señal, ejecutando programas simultáneamente o mediante hardware especial tal como registros de control de E/S asignados a la memoria. Puede declarar una variable como volatile mientras dure o puede convertir una única referencia para que sea volatile.

  • Un elemento puede ser a la vez const y volatile , en cuyo caso el elemento no podría modificarlo de manera legítima su propio programa, pero podría modificarlo algún proceso asincrónico.

restrict

El calificador de tipo restrict, incluido por primera vez en C99 y disponible en los modos /std:c11 y /std:c17, se puede aplicar a las declaraciones de puntero. Califica el puntero, no lo que señala.

restrict es una sugerencia de optimización para el compilador de que ningún otro puntero del ámbito actual haga referencia a la misma ubicación de memoria. Es decir, solo se usa el puntero o un valor derivado de él (por ejemplo, puntero + 1) para acceder al objeto durante la vigencia del puntero. Esto ayuda al compilador a generar código más optimizado. C++ tiene un mecanismo equivalente, __restrict.

Tenga en cuenta que restrict es un contrato entre usted y el compilador. Si asigna un alias a un puntero marcado con restrict , el resultado es indefinido.

Este es un ejemplo donde se usa restrict :

void test(int* restrict first, int* restrict second, int* val)
{
    *first += *val;
    *second += *val;
}

int main()
{
    int i = 1, j = 2, k = 3;
    test(&i, &j, &k);

    return 0;
}

// Marking union members restrict tells the compiler that
// only z.x or z.y will be accessed in any scope, which allows
// the compiler to optimize access to the members.
union z 
{
    int* restrict x;
    double* restrict y;
};

Vea también

/std (Especificar la versión estándar del lenguaje)
Declaraciones y tipos