Costumo ouvir que, ao compilar programas em C e C ++, eu deveria "sempre ativar avisos do compilador". Por que isso é necessário? Como faço isso?
Às vezes, também ouço dizer que devo "tratar os avisos como erros". Eu devo? Como faço isso?
Costumo ouvir que, ao compilar programas em C e C ++, eu deveria "sempre ativar avisos do compilador". Por que isso é necessário? Como faço isso?
Às vezes, também ouço dizer que devo "tratar os avisos como erros". Eu devo? Como faço isso?
Respostas:
Os compiladores C e C ++ são notoriamente ruins em relatar alguns erros comuns do programador por padrão , como:
return
um valor de uma funçãoprintf
e scanf
famílias que não correspondem à string de formatoEles podem ser detectados e relatados, mas geralmente não são por padrão; esse recurso deve ser solicitado explicitamente por meio de opções do compilador.
Isso depende do seu compilador.
Microsoft C e compiladores C ++ compreender interruptores gosto /W1
, /W2
, /W3
, /W4
e /Wall
. Use pelo menos /W3
. /W4
e /Wall
pode emitir avisos espúrios para arquivos de cabeçalho do sistema, mas se o seu projeto compilar corretamente com uma dessas opções, siga-o. Essas opções são mutuamente exclusivas.
A maioria dos outros compiladores entende opções como -Wall
, -Wpedantic
e -Wextra
. -Wall
é essencial e todo o resto é recomendado (observe que, apesar do nome, -Wall
habilita apenas os avisos mais importantes, nem todos ). Essas opções podem ser usadas separadamente ou todas juntas.
Seu IDE pode ter uma maneira de habilitá-los na interface do usuário.
Um aviso do compilador sinaliza um problema potencialmente sério no seu código. Os problemas listados acima são quase sempre fatais; outros podem ou não, mas você deseja que a compilação falhe, mesmo que seja um alarme falso. Investigue cada aviso, encontre a causa raiz e corrija-a. No caso de um alarme falso, contorne-o, ou seja, use um recurso ou construção de idioma diferente para que o aviso não seja mais acionado. Se isso for muito difícil, desative esse aviso específico caso a caso.
Você não deseja apenas deixar avisos como avisos, mesmo que todos sejam falsos alarmes. Pode ser bom para projetos muito pequenos em que o número total de avisos emitidos seja menor que 7. Mais alguma coisa, e é fácil que um novo aviso se perca em uma enxurrada de velhos e familiares. Não permita isso. Apenas faça com que todo o seu projeto seja compilado de maneira limpa.
Observe que isso se aplica ao desenvolvimento do programa. Se você estiver lançando seu projeto para o mundo no formulário de origem, pode ser uma boa idéia não fornecer -Werror
ou equivalente no script de construção liberado . As pessoas podem tentar criar seu projeto com uma versão diferente do compilador ou com um compilador diferente, o que pode ter um conjunto diferente de avisos habilitados. Você pode querer que a construção deles seja bem-sucedida. Ainda é uma boa ideia manter os avisos ativados, para que as pessoas que vêem mensagens de aviso possam enviar relatórios ou correções de bugs.
Isso é feito novamente com opções de compilador. /WX
é para a Microsoft, a maioria dos outros usa -Werror
. Em ambos os casos, a compilação falhará se houver algum aviso produzido.
C é, notoriamente, uma linguagem de nível bastante baixo conforme os HLLs. O C ++, embora pareça ser uma linguagem de nível consideravelmente mais alto que o C, ainda compartilha algumas de suas características. E uma dessas características é que as linguagens foram projetadas por programadores, para programadores - e, especificamente, programadores que sabiam o que estavam fazendo.
[No restante desta resposta, vou focar em C. A maior parte do que direi também se aplica ao C ++, embora talvez não tão fortemente. Embora, como disse Bjarne Stroustrup, "C facilite o tiro no pé; o C ++ torna mais difícil, mas quando você o faz explodir toda a perna". ]
Se você sabe o que está fazendo - realmente sabe o que está fazendo -, às vezes você pode ter que "quebrar as regras". Mas na maioria das vezes, a maioria de nós concorda que regras bem-intencionadas nos mantêm longe de problemas, e que quebrar voluntariamente essas regras o tempo todo é uma má idéia.
Mas em C e C ++, há um número surpreendentemente grande de coisas que você pode fazer que são "más idéias", mas que não são formalmente "contrárias às regras". Às vezes, são uma péssima ideia algumas vezes (mas podem ser defensáveis outras vezes); às vezes, são uma má ideia praticamente o tempo todo. Mas a tradição sempre foi não avisar sobre essas coisas - porque, novamente, a suposição é que os programadores sabem o que estão fazendo, eles não fariam essas coisas sem uma boa razão, ficariam aborrecidos por muitos de avisos desnecessários.
Mas é claro que nem todos os programadores realmente sabem o que estão fazendo. E, em particular, todo programador C (não importa o quão experiente) passa por uma fase de ser um programador iniciante em C. E mesmo programadores C experientes podem se descuidar e cometer erros.
Finalmente, a experiência mostrou não apenas que os programadores cometem erros, mas que esses erros podem ter consequências reais e sérias. Se você cometer um erro, e o compilador não avisar sobre isso, e de alguma forma o programa não travar imediatamente ou fizer algo obviamente errado por causa disso, o erro pode estar lá, escondido, às vezes por anos, até causar um realmente grande problema.
Portanto, na maioria das vezes, os avisos são uma boa ideia, afinal. Até os programadores experientes aprenderam (na verdade, é " especialmente os programadores experientes aprenderam") que, no geral, os avisos tendem a fazer mais bem do que prejudicar. Sempre que você fez algo errado deliberadamente e o aviso foi um incômodo, provavelmente há pelo menos dez vezes que você fez algo errado por acidente e o aviso o salvou de mais problemas. E a maioria dos avisos pode ser desativada ou contornada nas poucas vezes em que você realmente deseja fazer a coisa "errada".
(Um exemplo clássico de como um "erro" é o teste if(a = b)
Na maioria das vezes, isso é um erro, por isso a maioria dos compiladores estes dias advertir sobre isso -.. Alguns até mesmo por omissão, mas se você realmente queria tanto Atribuir b
a a
e teste o resultado, você pode desativar o aviso digitando if((a = b))
.)
A segunda pergunta é: por que você deseja solicitar ao compilador que trate os avisos como erros? Eu diria que é por causa da natureza humana, especificamente, a reação muito fácil de dizer "Oh, isso é apenas um aviso, isso não é tão importante, eu vou limpar isso mais tarde". Mas se você é um procrastinador (e eu não o conheço, mas sou um péssimo procrastinador), é fácil adiar a limpeza necessariamente para sempre - e se você tem o hábito de ignorar os avisos, fica cada vez mais fácil perder uma importante mensagem de aviso que fica parada, despercebida, no meio de todas as que você está ignorando.
Portanto, pedir ao compilador que trate os avisos como erros é um pequeno truque que você pode usar para contornar esse inimigo humano.
Pessoalmente, não sou tão insistente em tratar avisos como erros. (De fato, se eu for honesto, posso dizer que praticamente nunca habilito essa opção na minha programação "pessoal".) Mas você pode ter certeza de que habilitei essa opção no trabalho, onde nosso guia de estilo (que eu escreveu) exige seu uso. E eu diria - suspeito que a maioria dos programadores profissionais diria - que qualquer loja que não trate avisos como erros em C está se comportando de maneira irresponsável, não está aderindo às melhores práticas do setor comumente aceitas.
if(a = b)
, portanto, não precisamos avisar." (Então, alguém produz uma lista de 10 bugs críticos em 10 produtos lançados esse resultado deste erro particular.) "Ok, não experiente programador C jamais iria escrever isso ..."
if (returnCodeFromFoo = foo(bar))
e dizer a verdade, para capturar e testar o código em um só lugar (suponha que o único objetivo foo
seja ter efeitos colaterais!) O fato de um programador realmente experiente saber que isso não é um bom estilo de codificação é irrelevante;)
if (returnCodeFromFoo = foo(bar))
, colocam um comentário e desativam o aviso (para que, quando o programador de manutenção o analise quatro anos depois, ele perceberá que o código é intencional. com alguém que (no país de Microsoft C ++) insistiu que combinar / Wall com tratar avisos como erros era o caminho a seguir.Uh, não é (a menos que você queira colocar muitos comentários de supressão).
Os avisos consistem nos melhores conselhos que alguns dos desenvolvedores de C ++ mais qualificados poderiam usar em um aplicativo. Vale a pena ficar por aqui.
O C ++, sendo uma linguagem completa de Turing, tem muitos casos em que o compilador deve simplesmente confiar que você sabia o que está fazendo. No entanto, existem muitos casos em que o compilador pode perceber que você provavelmente não pretendia escrever o que escreveu. Um exemplo clássico é printf () códigos que não correspondem aos argumentos, ou std :: cordas passados para printf (não que isso sempre acontece comigo!). Nesses casos, o código que você escreveu não é um erro. É uma expressão válida do C ++ com uma interpretação válida para a ação do compilador. Mas o compilador tem um forte palpite de que você simplesmente ignorou algo que é fácil para um compilador moderno detectar. Estes são avisos. São coisas óbvias para um compilador, usando todas as regras estritas do C ++ à sua disposição, que você pode ter esquecido.
Desativar avisos ou ignorá-los é como optar por ignorar o aconselhamento gratuito daqueles mais habilidosos que você. É uma lição de huberis que termina quando você voa muito perto do sol e suas asas derretem, ou ocorre um erro de corrupção de memória. Entre os dois, eu vou cair do céu qualquer dia!
"Tratar avisos como erros" é a versão extrema dessa filosofia. A idéia aqui é que você resolva todos os avisos que o compilador lhe der - ouça todos os conselhos gratuitos e aja de acordo. Se este é um bom modelo de desenvolvimento para você, depende da equipe e de que tipo de produto você está trabalhando. É a abordagem ascética que um monge pode ter. Para alguns, funciona muito bem. Para outros, não.
Em muitos dos meus aplicativos, não tratamos os avisos como erros. Fazemos isso porque esses aplicativos específicos precisam compilar em várias plataformas com vários compiladores de idades variadas. Às vezes, achamos que é realmente impossível corrigir um aviso de um lado sem que ele se transforme em um aviso em outra plataforma. Portanto, somos apenas cuidadosos. Nós respeitamos os avisos, mas não nos inclinamos para trás.
equals
/ inconsistente / hashCode
), e é um problema de qualidade de implementação quais delas são relatadas.
Não apenas o manuseio dos avisos cria um código melhor, como também o torna um programador melhor. Os avisos lhe dirão sobre coisas que podem parecer pouco para você hoje, mas um dia esse mau hábito voltará e o incomodará.
Use o tipo correto, retorne esse valor, avalie esse valor de retorno. Reserve um tempo e reflita "Esse é realmente o tipo correto neste contexto?" "Eu preciso devolver isso?" E o biggie; "Esse código será portátil pelos próximos 10 anos?"
Adquira o hábito de escrever código sem aviso prévio.
As outras respostas são excelentes e não quero repetir o que disseram.
Um outro aspecto do "por que ativar avisos" que não foi abordado adequadamente é que eles ajudam enormemente na manutenção do código. Quando você escreve um programa de tamanho significativo, torna-se impossível manter tudo na cabeça de uma só vez. Você normalmente tem uma função ou três nas quais está escrevendo e pensando ativamente, e talvez um arquivo ou três na tela que possa se referir, mas a maior parte do programa existe em segundo plano em algum lugar e você deve confiar que ele continua trabalhando.
Ter avisos e tê-los tão enérgicos quanto possível, ajuda a alertá-lo se algo que você mudar causar problemas para algo que você não pode ver.
Tomemos, por exemplo, o aviso de clang -Wswitch-enum
. Isso aciona um aviso se você usar uma opção em uma enumeração e perder um dos valores possíveis da enumeração. É algo que você pode pensar que seria um erro improvável de cometer: você provavelmente ao menos olhou para a lista de valores de enumeração ao escrever a instrução switch. Você pode até ter um IDE que gerou as opções de opção para você, sem deixar espaço para erro humano.
Esse aviso realmente ocorre quando, seis meses depois, você adiciona outra entrada possível ao enum. Novamente, se você estiver pensando no código em questão, provavelmente ficará bem. Mas se esse enum é usado para vários propósitos diferentes e é para um daqueles que você precisa da opção extra, é muito fácil esquecer de atualizar uma opção em um arquivo que você não tocou por 6 meses.
Você pode pensar em avisos da mesma maneira que em casos de teste automatizados: eles ajudam a garantir que o código seja sensato e a fazer o que você precisa quando você o escreve, mas ajudam ainda mais a garantir que ele continua fazendo o que você precisa enquanto estimula. A diferença é que os casos de teste funcionam muito estreitamente com os requisitos do seu código e você precisa escrevê-los, enquanto os avisos funcionam amplamente com padrões sensíveis para quase todo o código, e são muito generosamente fornecidos pelos boffins que fazem os compiladores.
A depuração de uma falha de segmentação, por exemplo, exige que o programador rastreie a raiz (causa) da falha, que geralmente está localizada em um local anterior no seu código do que a linha que eventualmente causou a falha de segmentação.
É muito típico que a causa seja uma linha para a qual o compilador emitiu um aviso que você ignorou e a linha que causou a segmentação falha na linha que acabou gerando o erro.
A correção do aviso leva à correção do problema. Um clássico!
Uma demonstração do acima. Considere o seguinte código:
#include <stdio.h>
int main(void) {
char* str = "Hello world!";
int idx;
// Colossal amount of code here, irrelevant to 'idx'
printf("%c\n", str[idx]);
return 0;
}
que, quando compilado com o sinalizador "Wextra" passado para o GCC, fornece:
main.c: In function 'main':
main.c:9:21: warning: 'idx' is used uninitialized in this function [-Wuninitialized]
9 | printf("%c\n", str[idx]);
| ^
que eu poderia ignorar e executar o código de qualquer maneira .. E então eu testemunharia uma "grande" falha de segmentação, como meu professor de epicurus de IP costumava dizer:
falha de segmentação
Para depurar isso em um cenário do mundo real, seria iniciado a partir da linha que causa a falha de segmentação e tentaria rastrear qual é a raiz da causa. Eles teriam que procurar o que aconteceu i
e str
dentro dessa quantidade colossal de código por lá ...
Até que, um dia, eles se encontraram na situação em que descobrem que idx
é usado não inicializado, portanto, ele tem um valor de lixo, o que resulta em indexar a string (muito) além de seus limites, o que leva a uma falha de segmentação.
Se eles não tivessem ignorado o aviso, teriam encontrado o bug imediatamente!
str[idx]
" não é "Ok, onde estão str
e idx
definidas?`
idx
o valor esperado em seu teste (não muito improvável se o valor esperado for 0) e apontar para alguns dados confidenciais que nunca devem ser impressos quando implantados.
Tratar avisos como erros é apenas um meio de autodisciplina: você estava compilando um programa para testar esse novo recurso brilhante, mas não pode até consertar as partes desleixadas. Não há informações adicionais Werror
, apenas as prioridades são definidas com muita clareza:
Não adicione novo código até corrigir os problemas no código existente
É realmente a mentalidade que é importante, não as ferramentas. A saída de diagnóstico do compilador é uma ferramenta. MISRA (para C incorporado) é outra ferramenta. Não importa qual você usa, mas sem dúvida os avisos do compilador são a ferramenta mais fácil que você pode obter (é apenas um sinalizador para definir) e a relação sinal / ruído é muito alta. Portanto, não há razão para não usá-lo.
Nenhuma ferramenta é infalível. Se você escrever const float pi = 3.14;
, a maioria das ferramentas não informará que você definiu π com uma precisão ruim, o que pode levar a problemas futuros. A maioria das ferramentas não abre uma sobrancelha if(tmp < 42)
, mesmo que seja conhecido que dar nomes sem sentido às variáveis e usar números mágicos é uma maneira de desastre em grandes projetos. Você precisa entender que qualquer código de "teste rápido" que você escreve é apenas isso: um teste, e você precisa corrigi-lo antes de prosseguir para outras tarefas, enquanto ainda vê suas deficiências. Se você deixar esses códigos como estão, a depuração se você passar dois meses adicionando novos recursos será significativamente mais difícil.
Depois de entrar na mentalidade certa, não há sentido em usá-lo Werror
. Ter avisos como avisos permitirá que você tome uma decisão informada se ainda faz sentido executar a sessão de depuração que você estava prestes a iniciar ou abortá-la e corrigir os avisos primeiro.
clippy
ferramenta de fiapos para o Rust realmente alertará sobre a constante "3,14". Na verdade, é um exemplo nos documentos . Mas, como você pode imaginar, clippy
tem orgulho em ser agressivamente útil.
Como alguém que trabalha com código C incorporado herdado, a ativação de avisos do compilador ajudou a mostrar muitas fraquezas e áreas a serem investigadas ao propor correções. Em gcc utilizando -Wall
e -Wextra
e até mesmo -Wshadow
tornaram-se vital. Não vou correr todos os riscos, mas vou listar alguns que apareceram que ajudaram a mostrar problemas de código.
Este pode facilmente apontar para trabalhos inacabados e áreas que podem não estar utilizando todas as variáveis passadas, o que pode ser um problema. Vejamos uma função simples que pode desencadear isso:
int foo(int a, int b)
{
int c = 0;
if (a > 0)
{
return a;
}
return 0;
}
Apenas compilar isso sem -Wall ou -Wextra não gera problemas. -Wall lhe dirá que isso c
nunca é usado:
foo.c: Na função 'foo':
foo.c: 9: 20: aviso: variável não utilizada 'c' [-Wunused-variable]
-Wextra também dirá que seu parâmetro b não faz nada:
foo.c: Na função 'foo':
foo.c: 9: 20: aviso: variável não utilizada 'c' [-Wunused-variable]
foo.c: 7: 20: aviso: parâmetro não utilizado 'b' [-Wunused-parameter] int foo (int a, int b)
Este foi um pouco difícil e não apareceu até que -Wshadow
foi usado. Vamos modificar o exemplo acima para adicionar apenas, mas acontece que existe um global com o mesmo nome de um local que causa muita confusão ao tentar usar os dois.
int c = 7;
int foo(int a, int b)
{
int c = a + b;
return c;
}
Quando -Wshadow foi ativado, é fácil identificar esse problema.
foo.c: 11: 9: aviso: a declaração de 'c' sombreia uma declaração global [-Wshadow]
foo.c: 1: 5: note: a declaração sombreada está aqui
Isso não requer nenhum sinalizador extra no gcc, mas ainda tem sido a fonte de problemas no passado. Uma função simples que tenta imprimir dados, mas tem um erro de formatação, pode se parecer com o seguinte:
void foo(const char * str)
{
printf("str = %d\n", str);
}
Isso não imprime a string, pois o sinalizador de formatação está errado e o gcc dirá com satisfação que provavelmente não é o que você queria:
foo.c: Na função 'foo':
foo.c: 10: 12: aviso: o formato '% d' espera o argumento do tipo 'int', mas o argumento 2 tem o tipo 'const char *' [-Wformat =]
Essas são apenas três das muitas coisas que o compilador pode verificar para você. Existem muitas outras como usar uma variável não inicializada que outras pessoas apontaram.
possible loss of precision
" e " comparison between signed and unsigned
". Acho difícil entender quantos "programadores" os ignoram (na verdade, não sei ao certo por que não são erros)
sizeof
não está assinado, mas o tipo inteiro padrão é assinado. O sizeof
tipo de resultado,, size_t
geralmente é usado para qualquer coisa relacionada ao tamanho do tipo, como, por exemplo, alinhamento ou contagem de elementos de matriz / contêiner, enquanto números inteiros em geral devem ser usados como "a int
menos que seja necessário". Considerando quantas pessoas são ensinadas a usar int
para iterar seus contêineres (em comparação int
com size_t
), cometer um erro quebraria praticamente tudo. ; P
Essa é uma resposta específica para C e por que isso é muito mais importante para C do que para qualquer outra coisa.
#include <stdio.h>
int main()
{
FILE *fp = "some string";
}
Esse código é compilado com um aviso . O que são e devem haver erros em praticamente todos os outros idiomas do planeta (exceto linguagem assembly) são avisos em C. Os avisos em C são quase sempre erros disfarçados. Os avisos devem ser corrigidos, não suprimidos.
Com gcc
, fazemos isso como gcc -Wall -Werror
.
Esse também foi o motivo da alta segurança de alguns avisos de API não seguros da MS. A maioria das pessoas que programa C aprendeu a maneira mais difícil de tratar os avisos como erros, e essas coisas pareciam não ser o mesmo tipo de coisa e queriam correções não portáteis.
AVISOS DO COMPILADOR SÃO SEU AMIGO (sem gritar, em maiúsculas para enfatizar).
Eu trabalho em sistemas Fortran-77 legados. O compilador me diz coisas valiosas: o tipo de dados do argumento não corresponde a uma chamada de sub-rotina, usando uma variável local antes que um valor tenha sido definido na variável, se eu tiver um argumento de variável ou sub-rotina que não seja usado. Estes são quase sempre erros.
Evitando uma postagem longa: quando meu código é compilado corretamente, 97% funciona. O outro cara com quem trabalho compila com todos os avisos desativados, passa horas ou dias no depurador e depois me pede ajuda. Acabei de compilar o código com os avisos e dizer o que corrigir.
Você sempre deve habilitar os avisos do compilador, pois o compilador geralmente pode lhe dizer o que há de errado com seu código. Para fazer isso, você passa -Wall -Wextra
para o compilador.
Normalmente, você deve tratar os avisos como erros, porque geralmente significam que há algo errado com o seu código. No entanto, geralmente é muito fácil ignorar esses erros. Portanto, tratá-los como erros fará com que a compilação falhe, portanto você não poderá ignorar os erros. Para tratar avisos como erros, passe -Werror
para o compilador.
Os avisos do compilador em C ++ são muito úteis por alguns motivos.
1 - Permite mostrar onde você pode ter cometido um erro que pode impactar o resultado final de suas operações. Por exemplo, se você não inicializou uma variável ou se colocou "=" em vez de "==" (existem apenas exemplos)
2 - Permite também mostrar onde seu código não está em conformidade com o padrão do c ++. É útil porque, se o código estiver em conformidade com o padrão real, será fácil movê-lo para outra forma de placa, por exemplo.
Em geral, os avisos são muito úteis para mostrar onde há erros no seu código que podem afetar o resultado do seu algoritmo ou evitar algum erro quando o usuário usar o seu programa.
Ignorar avisos significa que você deixou um código incorreto que não só poderia causar problemas no futuro para outra pessoa, mas também tornaria importantes as mensagens de compilação menos notadas por você. Quanto mais saída do compilador, menos alguém notará ou se incomodará. Limpador, melhor. Isso também significa que você sabe o que está fazendo. Os avisos são muito pouco profissionais, descuidados e arriscados.
Certa vez, trabalhei para uma grande empresa (Fortune 50) que fabricava equipamentos de teste eletrônico.
O produto principal do meu grupo foi um programa MFC que, ao longo dos anos, passou a gerar literalmente centenas de avisos. Que foram ignorados em quase todos os casos.
Este é um pesadelo quando ocorrem erros.
Após essa posição, tive a sorte de ser contratado como o primeiro desenvolvedor de uma nova startup.
Incentivei uma política de 'sem aviso' para todas as compilações, com os níveis de aviso do compilador configurados para serem bastante barulhentos.
Nossa prática era usar #pragma warning - push / disable / pop para o código que o desenvolvedor tinha certeza de que estava realmente bem, junto com uma declaração de log no nível de depuração, apenas por precaução.
Essa prática funcionou bem para nós.
#pragma warning
não apenas suprime avisos, serve para a dupla finalidade de comunicar rapidamente a outros programadores que algo é intencional e não acidental e atua como uma tag de pesquisa para localizar rapidamente áreas potencialmente problemáticas quando algo quebra, mas corrigir os erros / avisos não consertá-lo.
Há apenas um problema em tratar os avisos como erros: quando você usa código proveniente de outras fontes (por exemplo, bibliotecas micro $ ** t, projetos de código aberto), eles não fazem seu trabalho corretamente e compilar seu código gera toneladas de avisos.
Eu sempre escrevo meu código para que não gere avisos ou erros e o limpo até compilar sem gerar ruído estranho. O lixo com o qual tenho que trabalhar me assusta, e me surpreendo quando preciso criar um grande projeto e observar um fluxo de avisos, onde a compilação deve apenas anunciar quais arquivos foram processados.
Também documento meu código porque sei que o custo real do software é proveniente principalmente da manutenção, não de escrevê-lo inicialmente, mas essa é uma história diferente ...
-Wall
e você usa -Wall -Wextra
.
Algum aviso pode significar possível erro semântico no código ou possível UB. Por exemplo , ;
depois if()
, variável não utilizada, variável global mascarada por local ou comparação de assinado e não assinado. Muitos avisos estão relacionados ao analisador de código estático no compilador ou a violações do padrão ISO detectável em tempo de compilação, que "exigem diagnósticos". Embora essas ocorrências possam ser legais em um caso específico, elas resultariam de problemas de design na maioria das vezes.
Alguns compiladores, por exemplo, gcc, têm uma opção de linha de comando para ativar o modo "avisos como erros"; é uma ferramenta legal, se cruel, para educar codificadores iniciantes.
O fato de que os compiladores C ++ aceitar compilar o código que, obviamente, resulta em um comportamento indefinido em tudo é uma grande falha nos compiladores. A razão pela qual eles não corrigem isso é porque isso provavelmente quebraria algumas construções utilizáveis.
A maioria dos avisos deve ser erros fatais que impedem a conclusão da compilação. Os padrões para exibir apenas erros e fazer a compilação de qualquer maneira estão errados e se você não os substituir para tratar os avisos como erros e deixar alguns avisos, provavelmente você terminará com o programa travando e fazendo coisas aleatórias.
int i; if (fun1()) i=2; if (fun2()) i=3; char s="abcde"[i];
Este código exibe um comportamento indefinido se e somente se ambos fun1()
e fun2()
pode retornar false
na mesma execução de função. O que pode ou não ser verdade, mas como o compilador deve dizer?
Definitivamente, você deve habilitar avisos do compilador, pois alguns compiladores são ruins em relatar alguns erros comuns de programação, incluindo o seguinte:
-> inicializa uma variável é esquecida -> retorna um valor de uma função - - os argumentos simples nas famílias printf e scanf que não correspondem à sequência de formatação em que uma função é usada sem ser declarada anteriormente, embora aconteça apenas em c
Portanto, como essas funções podem ser detectadas e relatadas, geralmente não é o padrão; portanto, esse recurso deve ser solicitado explicitamente por meio de opções do compilador.
Acalme-se: você não precisa, não é necessário. -Wall e -Werror foram projetados por maníacos de refatoração de código para eles mesmos: foram inventados pelos desenvolvedores de compiladores para evitar a quebra de construções existentes após atualizações do compilador no lado do usuário . O recurso não é nada, mas tudo sobre a decisão de interromper ou não interromper a compilação.
É totalmente da sua preferência usá-lo ou não. Eu o uso o tempo todo porque me ajuda a corrigir meus erros.
-Wall and -Werror was designed by code-refactoring maniacs for themselves.
[citação necessário]
-Wall
e -Werror
, mas apenas perguntando se é uma boa ideia. Que, da sua última frase, parece que você está dizendo que sim.