Pergunta

Enquanto obtenho meu código revisado aqui a questão do uso do const palavra-chave surgiu.Entendo que é usado para implementar comportamento somente leitura em variáveis.

Estou confuso sobre quais são as várias situações em que isso pode ser útil.

  • Deveria ser usado por uma questão de clareza nos protótipos de funções?
  • Deve ser usado como medida de segurança durante o desenvolvimento do código?
  • Deveria ser usado no escopo de várias funções para declarar constantes de tempo de execução?
  • Deveria ser usado?

Essas perguntas são apenas exemplos da confusão que estou enfrentando.A confusão geral é

  • Quando deveria ser o const palavra-chave usada na programação C?
  • Quais são os vários tipos de benefícios que podem ser obtidos usando esta palavra-chave em C?
  • Há algum contras em usar const palavra-chave?


Foi apontado que esta questão pode ser muito ampla devido a todas essas questões nos detalhes da minha pergunta.Queria apenas esclarecer que essas perguntas são apenas para esclarecer a confusão em relação à questão principal.

Quando e com que finalidade a palavra-chave const deve ser usada em C para variáveis?

Também pode ser reformulado como

O uso adequado de const palavra-chave em C` com os prós e contras da mesma.

Foi útil?

Solução

Ao revisar o código, aplico as seguintes regras:

  • Sempre use const Para parâmetros de função passados ​​por referência em que a função não modifica (ou livre) os dados apontados.

    int find(const int *data, size_t size, int value);
    
  • Sempre use const para constantes que poderiam ser definidas usando um #define ou um enum.Como resultado, o compilador pode localizar os dados na memória somente leitura (ROM) (embora o vinculador seja frequentemente uma ferramenta melhor para esse propósito em sistemas embarcados).

    const double PI = 3.14;
    
  • Nunca use const em uma função protótipo para um parâmetro passado porvalor.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, int value); 
    
  • Quando apropriado, use const volatile em locais que não podem ser alterados pelo programa, mas que ainda podem ser alterados.Os registros de hardware são o caso de uso típico aqui, por exemplo, um registro de status que reflete o estado de um dispositivo:

    const volatile int32_t *DEVICE_STATUS =  (int32_t*) 0x100;
    

Outros usos são opcionais.Por exemplo, os parâmetros para uma função dentro da função implementação pode ser marcado 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 valores de retorno de função 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 de const apenas indique que não irá alterar a variável;eles não mudam como ou onde a variável é armazenada.É claro que o compilador pode descobrir que uma variável não foi alterada, mas adicionando const você permite que ele imponha isso.Isso pode ajudar o leitor e adicionar alguma segurança (embora se suas funções são grandes ou complicadas o suficiente para que isso faça uma grande diferença, você tem 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 certas variáveis ​​nunca mudam podem aliviar significativamente o subestão.Tais funções foram mal projetadas ou mantidas.


Problemas com const.Você provavelmente ouvirá o termo "envenenamento constante".Isso ocorre ao adicionar const Para um parâmetro de função, faz com que a 'consistência' se propus.

Editar - envenenamento const:por exemplo na função:

int function_a(char * str, int n)
{
    ...
    function_b(str);
    ...
}

se nós mudarmos str para const, devemos então garantir que fuction_b Também leva um const.E assim por diante se function_b passa o str para function_c, etc.Como você pode imaginar, isso pode ser doloroso se se propagar em muitos arquivos/módulos separados.Se se propagar em uma função que não pode ser alterada (por exemplo, uma biblioteca do sistema), será necessário um elenco.Então polvilhandoconst no código existente talvez esteja causando problemas.No novo código, porém, é melhor const qualifique-se consistentemente quando apropriado.

O problema mais insidioso const é que não estava no idioma original.Como complemento, não cabe bem.Para começar, ele tem dois significados (como nas regras acima, o que significa "não vou mudar isso" e "isso não pode ser modificado").Mas mais do que isso, pode ser perigoso.Por exemplo, compilar e executar este código e (dependendo do compilador/opções), ele pode travar quando executado:

const char str[] = "hello world\n";
char *s = strchr(str, '\n');
*s = '\0';

strchr retorna um char* não é um const char*.Como seu parâmetro de chamada éconst deve elenco o parâmetro de chamada para char*.E, neste caso, que afasta a verdadeira propriedade de armazenamento somente leitura. Editar:- isso se aplica geralmente a vars na memória somente leitura.Por 'ROM', quero dizer não apenas ROM física, mas qualquer memória protegida contra gravação, como acontece com a seção de código de programas executados em um sistema operacional típico.

Muitas funções de biblioteca padrão se comportam da mesma maneira, então tome cuidado:quando voce tem real constantes (ou seja,armazenado em ROM) Você deve ter muito cuidado para não perder a constituição deles.

Outras dicas

Geralmente em qualquer linguagem de programação é recomendado usar const ou o modificador equivalente desde

  • Pode esclarecer ao chamador que o que ele transmitiu não vai mudar
  • Potenciais melhorias de velocidade, já que o compilador sabe com certeza que pode omitir certas coisas que só são relevantes se o parâmetro puder ser alterado
  • Proteção contra você mesmo alterando acidentalmente o valor

De acordo com as declarações do TheLQ:

Ao trabalhar com uma equipe de programadores declarando const é uma boa forma de indicar que tal variável não deve ser modificada, ou apenas para se lembrar em grandes projetos.É útil nesse sentido e pode evitar muitas dores de cabeça.

Sim, é basicamente a resposta do TheLQ.

É uma medida de segurança do programador para não modificar uma variável, e para não chamar funções que possam modificá-las.Em um array ou estrutura o especificador const indica que os valores de seu conteúdo não serão modificados, e mesmo o compilador não permitirá que você faça isso.Você ainda pode alterar facilmente o valor da variável com apenas uma conversão.

No que costumo ver, é usado principalmente para adicionar valores constantes no código e para indicar que o array ou estrutura não será modificado se você chamar uma função específica.Esta última parte é importante, porque quando você chama uma função que VAI modificar seu array ou estrutura, você pode querer manter a versão original, então você cria uma cópia da variável e depois a passa para a função.Se não for esse o caso, você não precisa da cópia, obviamente, então por exemplo você pode alterar,

int foo(Structure s);

para

int foo(const Structure * s);

e não obtendo sobrecarga de cópia.

Apenas para acrescentar, observe que C possui regras específicas com o especificador const.Por exemplo,

int b = 1;
const int * a = &b;

não é o mesmo que

int b = 1;
int * const a = &b;

O primeiro código não permitirá que você modifique a.No segundo caso, o ponteiro é constante, mas o seu conteúdo não é, então o compilador permitirá que você diga * a = 3; sem um erro do compilador, mas você não pode fazer a ser uma referência a outra coisa.

Licenciado em: CC-BY-SA com atribuição
scroll top