Partilhar via


Qualificadores de tipo

Os qualificadores de tipo dão uma das duas propriedades a um identificador. O const qualificador de tipo declara um objeto como não modificável. O volatile qualificador de tipo declara um item cujo valor pode ser legitimamente alterado por algo fora do controle do programa no qual aparece, como um thread em execução simultânea.

Os qualificadores de tipo, const, restrict, e volatile, só podem aparecer uma vez em uma declaração. Os qualificadores de tipo podem aparecer com qualquer especificador de tipo; no entanto, eles não podem aparecer após a primeira vírgula em uma declaração de vários itens. Por exemplo, as seguintes declarações são legais:

typedef volatile int VI;
const int ci;

Estas declarações não são legais:

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

Os qualificadores de tipo são relevantes apenas ao acessar identificadores como valores l em expressões. Consulte Expressões de valor L e valor R para obter informações sobre valores e expressões L.

Sintaxe

type-qualifier:
const
restrict
volatile

const e volatile

São legais const e volatile declarações:

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

Se a especificação de um tipo de matriz incluir qualificadores de tipo, o elemento será qualificado, não o tipo de matriz. Se a especificação do tipo de função incluir qualificadores, o comportamento será indefinido. volatile e const não afetam o intervalo de valores ou propriedades aritméticas do objeto.

  • A const palavra-chave pode ser usada para modificar qualquer tipo fundamental ou agregado, ou um ponteiro para um objeto de qualquer tipo, ou um typedef. Se um item é declarado apenas com o qualificador de const tipo, seu tipo é considerado const int. Uma const variável pode ser inicializada ou colocada em uma região somente leitura de armazenamento. A const palavra-chave é útil para declarar ponteiros para const , uma vez que isso requer que a função não altere o ponteiro de forma alguma.

  • O compilador assume que, em qualquer ponto do programa, uma volatile variável pode ser acessada por um processo desconhecido que usa ou modifica seu valor. Independentemente das otimizações especificadas na linha de comando, o código para cada atribuição ou referência de uma volatile variável deve ser gerado, mesmo que pareça não ter efeito.

Se volatile for usado sozinho, int é assumido. O volatile especificador de tipo pode ser usado para fornecer acesso confiável a locais de memória especiais. Use volatile com objetos de dados que podem ser acessados ou alterados por manipuladores de sinal, por programas em execução simultânea ou por hardware especial, como registradores de controle de E/S mapeados pela memória. Você pode declarar uma variável quanto volatile ao seu tempo de vida ou pode converter uma única referência para ser volatile.

  • Um item pode ser ambos const e volatile, caso em que o item não poderia ser legitimamente modificado por seu próprio programa, mas poderia ser modificado por algum processo assíncrono.

restrict

O restrict qualificador de tipo, introduzido em C99 e disponível em /std:c11 ou /std:c17 modo, pode ser aplicado a declarações de ponteiro. Qualifica o ponteiro, não o que aponta.

restrict é uma dica de otimização para o compilador de que nenhum outro ponteiro no escopo atual se refere ao mesmo local de memória. Ou seja, apenas o ponteiro ou um valor derivado dele (como ponteiro + 1) é usado para acessar o objeto durante o tempo de vida do ponteiro. Isso ajuda o compilador a produzir um código mais otimizado. C++ tem um mecanismo equivalente, __restrict

Tenha em mente que restrict é um contrato entre você e o compilador. Se você fizer um alias marcado com restrict, o resultado será indefinido.

Aqui está um exemplo que 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;
};

Ver também

/std (Especificar versão padrão do idioma)
Declarações e Tipos