Pergunta

Um cliente realizou recentemente a análise estática da base de código C do meu empregador e nos deu os resultados. Entre os patches úteis estava o pedido para mudar o famoso do { ... } while(0) macro para do { ... } while(0,0). Eu entendo o que o patch deles está fazendo (usando o operador de sequência para Retorna Avalie o valor do segundo "0", então o efeito é o mesmo), mas não está claro por que eles favoreceriam a segunda forma sobre a primeira forma.

Existe uma razão legítima pela qual se deve preferir a segunda forma da macro, ou a análise estática de nosso cliente é excessivamente pedante?

Foi útil?

Solução

Bem, eu vou para uma resposta:

Existe uma razão legítima para preferir a segunda forma da macro ...?

Não. Não há razão legítima. Ambos sempre se avaliam como False, e qualquer compilador decente provavelmente transformará o segundo na primeira na assembléia. Se houve algum motivo para ser inválido em alguns casos, C já existe há muito tempo para que esse motivo seja descoberto por Gurus Grande que eu.

Se você gosta do seu código fazendo olhos de coruja para você, use while(0,0). Caso contrário, use o que o restante do mundo da programação C usa e informe a ferramenta de análise estática do seu cliente para empurrá -la.

Outras dicas

Apenas um palpite sobre por que eles podem sugerir usar

do { ... } while(0,0)

sobre

do { ... } while(0)

Embora não haja diferença de comportamento e não deva haver diferença de custo de execução entre os dois.

Meu palpite é que a ferramenta de análise estática reclama sobre o while loop sendo controlado por uma constante no caso mais simples e não 0,0 é usado. A sugestão do cliente é provavelmente apenas para que eles não recebam um monte de falsos positivos da ferramenta.

Por exemplo, ocasionalmente encontro situações em que quero ter uma declaração condicional controlada por uma constante, mas o compilador reclamará com um aviso sobre uma expressão condicional avaliada para uma constante. Então eu tenho que pular por alguns aros para fazer com que o compilador pare de reclamar (já que não gosto de ter avisos espúrios).

A sugestão do seu cliente é um dos aros que eu usei para acalmar esse aviso, embora no meu caso não estivesse controlando um while Loop, era para lidar com uma afirmação "sempre falha". Ocasionalmente, terei uma área de código que nunca deve ser executada (talvez o caso padrão de um switch). Nessa situação, posso ter uma afirmação que sempre falha com alguma mensagem:

assert( !"We should have never gotten here, dammit...");

Mas, pelo menos um compilador que eu uso questões um aviso sobre a expressão sempre avaliada como falsa. No entanto, se eu mudar para:

assert( ("We should have never gotten here, dammit...", 0));

O aviso desaparece e todo mundo está feliz. Suponho que até a ferramenta de análise estática do seu cliente também seria. Observe que geralmente escondo esse pedaço de aro pulando atrás de uma macro como:

#define ASSERT_FAIL( x) assert( ((x), 0))

Pode ser bom poder dizer ao fornecedor da ferramenta para corrigir o problema, mas pode haver casos legítimos em que eles realmente querem diagnosticar um loop sendo controlado por uma expressão booleana constante. Sem mencionar o fato de que, mesmo que você convença um fornecedor de ferramentas a fazer essa mudança, isso não o ajuda no próximo ano ou para que possa ser necessário para realmente obter uma correção.

Usando while(0,0) Impede que a Microsoft Compiler gere um aviso sobre uma condição que é uma constante (aviso C4127).

Quando esse aviso é ativado (por exemplo, com /w4 ou /parede), ele pode ser desligado caso a caso com esse pequeno truque (bom belo (Veja este outro tópico).

EDIT: Desde Visual Studio 2017 15.3, while(0) não emite mais avisos (cf. Condicionais constantes). Você pode se livrar do seu (0,0) !

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top