Em C e C ++, é muito fácil escrever o código a seguir com um erro grave.
char responseChar = getchar();
int confirmExit = 'y' == tolower(responseChar);
if (confirmExit = 1)
{
exit(0);
}
O erro é que a instrução if deveria ter sido:
if (confirmExit == 1)
Conforme codificado, ele sai sempre, porque confirmExit
ocorre a atribuição da variável e confirmExit
é usado como resultado da expressão.
Existem boas maneiras de evitar esse tipo de erro?
c++
coding-standards
DesenvolvedorDon
fonte
fonte
if (confirmExit)
.a = b
oua == b
dentro de uma condicional.Respostas:
A melhor técnica é aumentar o nível de aviso do seu compilador. Em seguida, ele será avisado sobre uma possível atribuição na condição condicional.
Certifique-se de compilar seu código com zero avisos (o que você deve fazer de qualquer maneira). Se você quiser ser pedante, configure seu compilador para tratar os avisos como erros.
Usar condicionais Yoda (colocar a constante no lado esquerdo) foi outra técnica popular há cerca de uma década. Mas eles tornam o código mais difícil de ler (e, portanto, mantêm por causa da maneira artificial de ler (a menos que você seja Yoda)) e não oferecem maiores benefícios do que aumentar o nível de aviso (que também traz benefícios extras de mais avisos).
Os avisos são realmente erros lógicos no código e devem ser corrigidos.
fonte
if (0 == ret)
horror.a == b
!!0==a && 0==b || 1==a && 1==b || 2==a && 2==b || ...
(repita para todos os valores possíveis). Não se esqueça do...|| 22==a && 22==b || 23==a && 24==b || 25==a && 25==b ||
erro obrigatório ... ou os programadores de manutenção não se divertirão.Você sempre pode fazer algo radical como testar seu software. Eu nem me refiro a testes de unidade automatizados, apenas os testes que todo desenvolvedor experiente faz por hábito executando seu novo código duas vezes, uma vez confirmando a saída e outra não. Essa é a razão pela qual a maioria dos programadores considera isso um problema.
fonte
rc=MethodThatRarelyFails(); if(rc = SUCCESS){
mais de uma vez, especialmente se o método falhar apenas em condições difíceis de testar.Uma maneira tradicional de impedir o uso incorreto de atribuições na expressão é colocar a constante à esquerda e a variável à direita.
O compilador relatará um erro para a atribuição ilegal a uma constante semelhante à seguinte.
A condição revisada se:
Como mostrado pelos comentários abaixo, este é considerado por muitos um método inadequado.
fonte
Concordo com todos que dizem "avisos do compilador", mas quero adicionar outra técnica: Revisões de código. Se você tem uma política de revisar todo o código que é confirmado, de preferência antes de ser confirmado, é provável que esse tipo de coisa seja detectado durante a revisão.
fonte
Primeiro, aumentar seus níveis de alerta nunca é demais.
Se você não deseja que sua condicional teste o resultado de uma atribuição na própria instrução if, depois de ter trabalhado com muitos programadores de C e C ++ ao longo dos anos, e nunca ouviu falar que comparar a constante primeiro
if(1 == val)
era uma coisa ruim, poderia tentar essa construção.Se o seu líder de projeto aprovar isso, não se preocupe com o que as outras pessoas pensam. A prova real é se você ou outra pessoa pode entender seu código daqui a meses e anos.
Se você pretendia testar o resultado de uma tarefa, no entanto, o uso de avisos mais altos pode [provavelmente ter] levado a tarefa a uma constante.
fonte
if ( auto myPtr = dynamic_cast<some_ptr>(testPtr) ) {
porque evita manter umnullptr
escopo inútil se a conversão falhar - o que é provavelmente o motivo pelo qual o C ++ tem essa capacidade limitada de atribuir dentro de uma condicional. Quanto ao resto, sim, uma definição deve ter sua própria linha, eu diria - muito mais fácil de ver de relance e menos propenso a diversos deslizes da mente.Tarde para a festa como sempre, mas a Análise de código estático é a chave aqui
A maioria dos IDEs agora fornece SCA além da verificação sintática do compilador, e outras ferramentas estão disponíveis, incluindo aquelas que implementam as diretrizes MISRA (*) e / ou CERT-C.
Declaração: Faço parte do grupo de trabalho MISRA C, mas estou postando a título pessoal. Eu também sou independente de qualquer fornecedor de ferramentas
fonte
Basta usar a atribuição à esquerda, os avisos do compilador podem ajudar, mas você precisa garantir o nível certo, caso contrário você será inundado com avisos inúteis ou não receberá os avisos que deseja ver.
fonte