Qualificadores de tipo
Os qualificadores de tipo fornecem uma de duas propriedades a um identificador. O qualificador de tipo const
declara um objeto como não modificável. O qualificador de tipo volatile
declara um item cujo valor possa ser alterado legitimamente para algo além do controle do programa em que aparece como um thread de execução simultânea.
Os qualificadores de tipo, const
, restrict
e volatile
, podem aparecer apenas uma vez em uma declaração. Os qualificadores de tipo podem aparecer com qualquer especificador de tipo; porém, não podem aparecer depois da primeira vírgula em uma declaração de vários itens. Por exemplo, as seguintes declarações são aceitáveis:
typedef volatile int VI;
const int ci;
Essas 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 l-values nas expressões. Consulte Expressões L-Value e R-Value para obter informações sobre l-values e expressões.
Sintaxe
type-qualifier
:
const
restrict
volatile
const
e volatile
Os exemplos abaixo são declarações const
e volatile
legais:
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á qualificada, não o tipo de matriz. Se a especificação de tipo de função incluir qualificadores, o comportamento será indefinido. volatile
e const
não afetam o alcance de valores ou propriedades aritméticas do objeto.
A palavra-chave
const
pode ser usada para modificar qualquer tipo fundamental ou de agregação, um ponteiro para um objeto de qualquer tipo ou umtypedef
. Se um item for declarado apenas com o qualificador de tipoconst
, seu tipo é considerado const int. Uma variávelconst
pode ser inicializada ou pode ser colocada em uma região de armazenamento somente leitura. A palavra-chaveconst
é útil para declarar ponteiros paraconst
, pois isso requer que a função não altere o ponteiro de nenhuma maneira.O compilador pressupõe que, a qualquer momento no programa, uma variável de
volatile
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 a uma variávelvolatile
deverá ser gerado mesmo se isso não tiver qualquer efeito aparente.
Se volatile
for usado sozinho, int
será presumido. O especificador de tipo volatile
pode ser usado para fornecer acesso confiável aos locais especiais de memória. Use volatile
com objetos de dados que possam ser acessados ou modificados por manipuladores de sinal, por programas de execução simultânea ou por hardware especial, como registros de controle de E/S mapeadas em memória. Você pode declarar uma variável como volatile
para seu tempo de vida, ou você pode determinar que uma única referência seja volatile
.
- Um item pode ser
const
evolatile
ao mesmo tempo. Nesse caso, ele não pode ser modificado legitimamente por seu próprio programa, mas pode ser modificado por algum processo assíncrono.
restrict
O qualificador de tipo restrict
, introduzido em C99 e disponível no modo /std:c11
ou /std:c17
, pode ser aplicado a declarações de ponteiro. Ele qualifica o ponteiro, não o que ele aponta.
restrict
é uma dica de otimização para o compilador que nenhum outro ponteiro no escopo atual se refere ao mesmo local de memória. Ou seja, somente 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. O C++ tem um mecanismo equivalente, __restrict
Tenha em mente que restrict
é um contrato entre você e o compilador. Se você fizer um alias com um ponteiro marcado com restrict
, o resultado será indefinido.
Veja 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;
};
Confira também
/std
(Especificar a versão padrão da linguagem)
Declarações e tipos