Ao revisar o código, aplico as seguintes regras:
Sempre use constpara parâmetros de função passados por referência onde a função não modifica (ou libera) os dados apontados.
int find(const int *data, size_t size, int value);
Sempre use constpara constantes que, de outra forma, poderiam ser definidas usando um #define ou um enum. O compilador pode localizar os dados na memória somente leitura (ROM) como resultado (embora o vinculador seja frequentemente uma ferramenta melhor para essa finalidade em sistemas incorporados).
const double PI = 3.14;
Nunca use const em um protótipo de função para um parâmetro passado por
valor . Não tem significado e, portanto, é apenas "ruído".
// don't add const to 'value' or 'size'
int find(const int *data, size_t size, const int value);
Onde apropriado, use const volatileem locais que não podem ser alterados pelo programa, mas que ainda podem mudar. Os registros de hardware são o caso de uso típico aqui, por exemplo, um registro de status que reflete um estado do dispositivo:
const volatile int32_t *DEVICE_STATUS = (int32_t*) 0x100;
Outros usos são opcionais. Por exemplo, os parâmetros para uma função na implementação da função podem ser marcados como const.
// 'value' and 'size can be marked as const here
int find(const int *data, const size_t size, const int value)
{
... etc
ou função retornam valores ou cálculos que são obtidos e nunca mudam:
char *repeat_str(const char *str, size_t n)
{
const size_t len = strlen(str);
const size_t buf_size = 1 + (len * n);
char *buf = malloc(buf_size);
...
Esses usos constapenas indicam que você não alterará a variável; eles não mudam como ou onde a variável é armazenada. Obviamente, o compilador pode descobrir que uma variável não é alterada, mas adicionando constvocê permite que isso seja imposto. Isso pode ajudar o leitor e adicionar um pouco de segurança (embora, se suas funções forem grandes ou complicadas o suficiente para que isso faça uma grande diferença, você possa ter outros problemas). Editar - por exemplo. uma função densamente codificada de 200 linhas com loops aninhados e muitos nomes de variáveis longos ou semelhantes, sabendo que determinadas variáveis nunca mudam podem facilitar a compreensão significativa. Tais funções foram mal projetadas ou mantidas.
Problemas com const. Você provavelmente ouvirá o termo "envenenamento const". Isso ocorre quando adicionar constum parâmetro de função faz com que 'constness' se propague.
Edit - envenenamento const: por exemplo, na função:
int function_a(char * str, int n)
{
...
function_b(str);
...
}
se mudarmos strpara const, devemos garantir que isso fuction_btambém leva a const. E assim por diante, se function_bpassa strpara function_cetc. Como você pode imaginar, isso pode ser doloroso se propagar em muitos arquivos / módulos separados. Se ele se propagar para uma função que não pode ser alterada (por exemplo, uma biblioteca do sistema), uma conversão se torna necessária. Portanto, espalhar o
constcódigo existente talvez esteja causando problemas. No entanto, no novo código, é melhor constqualificar - se consistentemente, quando apropriado.
O problema mais insidioso consté que ele não estava no idioma original. Como complemento, ele não se encaixa perfeitamente. Para começar, ele tem dois significados (como nas regras acima, significando "Não vou mudar isso" e "isso não pode ser modificado"). Mas mais do que isso, pode ser perigoso. Por exemplo, compile e execute esse código e (dependendo do compilador / opções) poderá travar ao executar:
const char str[] = "hello world\n";
char *s = strchr(str, '\n');
*s = '\0';
strchrretorna um char*não a const char*. Como seu parâmetro de chamada,
constele deve converter o parâmetro de chamada para char*. E, nesse caso, isso elimina a propriedade de armazenamento real somente leitura. Editar: - isso se aplica geralmente a vars na memória somente leitura. Por 'ROM', quero dizer não apenas a ROM física, mas qualquer memória protegida contra gravação, como acontece com a seção de código dos programas executados em um sistema operacional típico.
Muitas funções padrão da biblioteca se comportam da mesma maneira, portanto, tenha cuidado: quando você tem constantes reais (ou seja, armazenadas na ROM), você deve ter muito cuidado para não perder a consistência.
Specific issues with software development. Eu estou sendo bem específico.