O qualificador 'restrict' em C
Entendendo o uso
O qualificador restrict diz ao compilador que um ponteiro não tem um aliasing, ou seja, não existe outro ponteiro que modifique o objeto 1. Por exemplo, uma função que possui a assinatura int f(int *a, int *b)
, os ponteiros a
e b
podem apontar para o mesmo objeto. O compilador tem que levar isso em consideração ao gerar o código.
Se sabemos que os ponteiros não apontam para o mesmo objeto, dizemos isso ao compilador usando a palavra-chave restrict. Isso permite que o código possa ser melhor otimizado.
Por exemplo, tome as funções f
e g
abaixo. A única diferença entre elas é a assinatura.
|
|
Veja o código gerado, com GCC, abaixo.
|
|
Na função f
, temos três acessos à memória. Isso ocorre porque quando atualizamos o valor de *b
, o compilador não tem garantia de que o objeto *a
não foi modificado. Assim, para retornar o valor de *a
, um novo acesso à memória é feito ao invés de, apenas, preservar o valor previamente atribuído.
A função g
, devido a não precisar carregar novamente o valor de *a
, possui um acesso à memória a menos. Aqui o compilador pode assumir que o valor de *a
não é alterado após a atribuição inicial.
Strict aliasing
O compilador GCC possui a opção -fstrictest aliasing
, habilitada nos níveis de otimização-O2
, -O3
e -Os
2. Com essa opção, o compilador segue uma regra que diz, ponteiros de tipos diferentes não apontam para o mesmo objeto. A exceção a regra são ponteiros do tipo char
, que podem ser aliases para qualquer tipo.
Caso a função f
, apresentada acima, fosse implementada com a assinatura long f(long *a, int *b)
, ou seja, ponteiros para tipos diferentes, e compilada com a opção -fstrictest aliasing
, teríamos o mesmo efeito de usar o modificador restrict. O compilador assumirá, nesse caso, que os ponteiros não apontam para o mesmo objeto e irá otimizar o código.
Conclusão
Caso tenha uma função que tenha mais de 1 ponteiro do mesmo tipo em seus parâmetros, ou que tenha mais de 1 ponteiro e algum deles é do tipo char
, use o modificador restrict para habilitar melhor otimização no código. Claro, contanto que os ponteiros não apontem para o mesmo lugar. Utilizar um nível de otimização de, pelo menos, -O2
. Para habilitar a regra de aliasing automaticamente para ponteiros de tipos diferentes.