C Avisos (-Wall -Wextra)
Um erro impede o programa de existir. Um aviso (warning) deixa o programa ser criado, mas o compilador comenta: "isto aqui está com cara de engano". Muitos iniciantes ignoram os avisos, porque "o programa rodou". Nesta aula você vai ver, com resultados reais, programas que compilam, rodam e dão a resposta errada, e como o compilador avisou de cada um deles, para quem pediu.
- A diferença entre aviso e erro, e como reconhecer um aviso na tela.
- O que
-Walle-Wextraligam, e por que não vêm ligados de fábrica. - Os avisos que salvam programas: formato errado no
printf,=no lugar de==,intcomparado comunsigned, variável sem valor e outros. - Por que alguns avisos só aparecem com
-O2. - Os avisos que o gcc 15 já trata como erro.
-Werror(avisos viram erros),-Wconversion(mais avisos) e-w(que você nunca deve usar).
Os programas foram compilados na máquina fictícia da Ana com o gcc 15.2, na pasta ~/c/avisos, e as mensagens do Clang são as do editor do guia. Alguns usam recursos das próximas aulas (variáveis, if); para esta aula, basta entender a ideia de cada um, que está explicada ao lado.
A ideia: a luz do painel do carro
Quando a luz do óleo acende no painel, o carro continua andando. Dá para ir trabalhar, voltar, passar a semana assim. Até o dia em que o motor funde. A luz não era o problema: era o aviso do problema.
Os avisos do compilador são essas luzes. E, por padrão, o gcc vem com quase todas elas desligadas, para não incomodar quem compila código antigo (há programas em C com 40 anos de idade, e eles teriam milhares de avisos). As opções -Wall e -Wextra, que você conheceu em Compilar com gcc, acendem o painel.
1. Aviso × erro
Erro (error:) | Aviso (warning:) | |
|---|---|---|
| O código segue as regras do C? | Não | Sim |
| O programa é criado? | Não | Sim |
| Quer dizer que… | "Não entendi o que você escreveu." | "Entendi, mas duvido que você quisesse isso." |
| No fim da mensagem | (nada, ou o nome do aviso que virou erro) | O nome do aviso entre colchetes, como [-Wunused-variable] |
Um aviso tem o mesmo formato de um erro (aula Lendo Erros do Compilador), com warning: no lugar de error::
#include <stdio.h>
int main(void) {
int itens = 3;
printf("Lista de compras da Ana\n");
return 0;
}
$ gcc -std=c23 compras.c -o compras
$ « sem -Wall: silêncio
$ gcc -std=c23 -Wall -Wextra compras.c -o compras
compras.c: In function ‘main’:
compras.c:4:9: warning: unused variable ‘itens’ [-Wunused-variable]
4 | int itens = 3;
| ^~~~~
- compras.c:4:9:
- Arquivo, linha e coluna, como num erro.
- warning:
- "Aviso". O programa foi criado.
- unused variable ‘itens’
- "Variável não usada:
itens". A Ana guardou o número 3 e nunca mais olhou para ele. - [-Wunused-variable]
- O nome do aviso: é a opção que o liga (e o termo para pesquisar, se a mensagem não ficar clara). Ele faz parte do grupo
-Wall.
Uma variável não usada não quebra nada. Mas é uma pista: ou sobrou de uma versão antiga do código (apague), ou você esqueceu de usá-la (a Ana queria mostrar "3 itens"). O aviso apontou o esquecimento.
2. O que -Wall e -Wextra ligam
-Wall(all, "todos"): liga os avisos que quase sempre indicam um problema real. Apesar do nome, não são todos.-Wextra(extra): liga mais alguns, um pouco mais exigentes.
Um aviso do -Wextra: a main pode receber as palavras digitadas depois do nome do programa (argc e argv, aula Argumentos da Linha de Comando). Receber e não usar dá aviso, mas só com -Wextra:
$ gcc -std=c23 -Wall args.c -o args « int main(int argc, char *argv[]) {
$ « só -Wall: nada
$ gcc -std=c23 -Wall -Wextra args.c -o args
args.c: In function ‘main’:
args.c:3:14: warning: unused parameter ‘argc’ [-Wunused-parameter]
3 | int main(int argc, char *argv[]) {
| ~~~~^~~~
args.c:3:26: warning: unused parameter ‘argv’ [-Wunused-parameter]
3 | int main(int argc, char *argv[]) {
| ~~~~~~^~~~~~
"Parâmetro não usado". Conserto: se a main não usa os argumentos, escreva int main(void), como o guia faz.
E há avisos que o gcc dá mesmo sem -Wall, de tão graves: os de formato errado no printf (seção 3.1) aparecem nos dois casos. Mas não conte com isso: a maioria, como o de função que não devolve valor (seção 3.6), só vem com -Wall. O Clang, o compilador do editor do guia, reconhece as mesmas opções e dá os avisos com os mesmos nomes entre colchetes. O editor compila sempre com -Wall -Wextra e mostra os avisos antes da saída do programa.
3. Avisos que salvam programas
3.1. Formato errado no printf
Cada lacuna do printf espera um tipo de valor: %d um inteiro, %f um número com vírgula (aula Formatos do printf). Trocar um pelo outro não dá erro, mas o resultado é lixo:
#include <stdio.h>
int main(void) {
int idade = 29;
double altura = 1.65;
printf("Idade: %f\n", idade);
printf("Altura: %d\n", altura);
return 0;
}
$ gcc -std=c23 -Wall -Wextra formato.c -o formato && ./formato
formato.c: In function ‘main’:
formato.c:6:21: warning: format ‘%f’ expects argument of type ‘double’, but argument 2 has type ‘int’ [-Wformat=]
6 | printf("Idade: %f\n", idade);
| ~^ ~~~~~
| | |
| | int
| double
| %d
formato.c:7:22: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘double’ [-Wformat=]
7 | printf("Altura: %d\n", altura);
| ~^ ~~~~~~
| | |
| int double
| %f
Idade: 0.000000 « a idade era 29!
Altura: -48263632 « lixo, que muda de uma vez para outra
"O formato %f espera um argumento do tipo double, mas o argumento 2 é do tipo int". Repare no desenho: embaixo da lacuna, o tipo que ela espera (double); embaixo do valor, o tipo que ele tem (int); e na última linha, a lacuna certa sugerida (%d). No Clang: format specifies type 'double' but the argument has type 'int', também com a sugestão.
Conserto: a lacuna do tipo certo: %d para a idade, %f (ou %.2f) para a altura.
Missão: rode e veja o lixo e os avisos. Troque as lacunas para o programa mostrar Idade: 29 e a altura começando por Altura: 1.65, sem nenhum aviso.
#include <stdio.h>
int main(void) {
int idade = 29;
double altura = 1.65;
printf("Idade: %f\n", idade);
printf("Altura: %d\n", altura);
return 0;
}
#include <stdio.h>
int main(void) {
int idade = 29;
double altura = 1.65;
printf("Idade: %d\n", idade);
printf("Altura: %.2f\n", altura);
return 0;
}
3.2. = no lugar de ==
Em C, = guarda um valor (atribuição) e == compara dois valores (aulas Atribuição e Comparação). Trocar um pelo outro é um dos erros mais comuns da programação. A Ana tirou 4 e quer parabenizar só quem tirou 10:
#include <stdio.h>
int main(void) {
int nota = 4;
if (nota = 10) {
printf("Nota máxima!\n");
}
printf("A nota é %d\n", nota);
return 0;
}
O if ("se") executa o bloco só se a condição for verdadeira (aula if e else). Ela queria escrever "se a nota for igual a 10", mas escreveu "guarde 10 na nota":
$ gcc -std=c23 igual.c -o igual && ./igual
Nota máxima! « errado: a nota era 4!
A nota é 10 « e pior: o 4 foi apagado e virou 10
$ gcc -std=c23 -Wall -Wextra igual.c -o igual && ./igual
igual.c: In function ‘main’:
igual.c:5:9: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
5 | if (nota = 10) {
| ^~~~
Nota máxima!
A nota é 10
Sem -Wall, compila em silêncio, roda, e as duas linhas estão erradas. Com -Wall: "sugiro parênteses em volta da atribuição usada como valor de verdade". Em outras palavras: "você usou uma atribuição (=) como condição; se era isso mesmo, ponha parênteses extras para eu saber". Quase nunca era. O Clang é ainda mais claro e oferece as duas saídas:
$ clang -std=c23 -Wall -Wextra igual.c -o igual
igual.c:5:14: warning: using the result of an assignment as a condition without parentheses [-Wparentheses]
5 | if (nota = 10) {
| ~~~~~^~~~
igual.c:5:14: note: place parentheses around the assignment to silence this warning
5 | if (nota = 10) {
| ^
| ( )
igual.c:5:14: note: use '==' to turn this assignment into an equality comparison
5 | if (nota = 10) {
| ^
| ==
1 warning generated.
A segunda nota: "use == para transformar esta atribuição numa comparação de igualdade". Conserto: if (nota == 10).
Missão: rode e veja o aviso. Corrija o programa para que ele não mostre "Nota máxima!" para uma nota 4, mostre A nota é 4 e compile sem nenhum aviso.
#include <stdio.h>
int main(void) {
int nota = 4;
if (nota = 10) {
printf("Nota máxima!\n");
}
printf("A nota é %d\n", nota);
return 0;
}
#include <stdio.h>
int main(void) {
int nota = 4;
if (nota == 10) {
printf("Nota máxima!\n");
}
printf("A nota é %d\n", nota);
return 0;
}
3.3. Comparar int com unsigned (só com -Wextra)
O C tem números inteiros com sinal (int, que aceita negativos) e sem sinal (unsigned int, só zero e positivos; aula Inteiros). Misturar os dois numa comparação dá um resultado surpreendente. A Ana está com o saldo negativo, −1, e o limite é 10:
#include <stdio.h>
int main(void) {
int saldo = -1;
unsigned int limite = 10;
if (saldo < limite) {
printf("Saldo abaixo do limite\n");
} else {
printf("Saldo OK\n");
}
return 0;
}
$ gcc -std=c23 -Wall sinal.c -o sinal && ./sinal
Saldo OK « −1 não é menor que 10?! E o -Wall não disse nada
$ gcc -std=c23 -Wall -Wextra sinal.c -o sinal && ./sinal
sinal.c: In function ‘main’:
sinal.c:6:15: warning: comparison of integer expressions of different signedness: ‘int’ and ‘unsigned int’ [-Wsign-compare]
6 | if (saldo < limite) {
| ^
Saldo OK
−1 é menor que 10, mas o programa disse que não. O que aconteceu: para comparar, o C converteu o -1 para unsigned, e −1 sem sinal vira um número enorme (4294967295), que não é menor que 10. O aviso "comparação de expressões inteiras com sinais diferentes" só veio com o -Wextra: em C, o -Wsign-compare não faz parte do -Wall. É um bom exemplo de por que o guia usa os dois. No Clang: comparison of integers of different signs: 'int' and 'unsigned int'.
Conserto: compare valores do mesmo tipo (aqui, int limite = 10;).
3.4. Variável sem valor
Em C, uma variável criada sem valor inicial (int pontos;) não vale zero: ela contém o que estiver naquele pedaço da memória, um valor "lixo". Usá-la antes de dar um valor é comportamento indefinido: o programa pode fazer qualquer coisa (aula Comportamento Indefinido).
$ cat semvalor.c
#include <stdio.h>
int main(void) {
int pontos;
printf("Pontos: %d\n", pontos);
return 0;
}
$ gcc -std=c23 semvalor.c -o semvalor && ./semvalor
Pontos: 0 « deu 0 por sorte; não conte com isso
$ gcc -std=c23 -Wall -Wextra semvalor.c -o semvalor
semvalor.c: In function ‘main’:
semvalor.c:5:5: warning: ‘pontos’ is used uninitialized [-Wuninitialized]
5 | printf("Pontos: %d\n", pontos);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
semvalor.c:4:9: note: ‘pontos’ was declared here
4 | int pontos;
| ^~~~~~
"pontos é usada sem ter sido inicializada" (sem valor inicial), e a note diz onde ela foi criada. O Clang ainda sugere o conserto:
$ clang -std=c23 -Wall -Wextra semvalor.c -o semvalor
semvalor.c:5:28: warning: variable 'pontos' is uninitialized when used here [-Wuninitialized]
5 | printf("Pontos: %d\n", pontos);
| ^~~~~~
semvalor.c:4:15: note: initialize the variable 'pontos' to silence this warning
4 | int pontos;
| ^
| = 0
1 warning generated.
Conserto: dê sempre um valor ao criar a variável: int pontos = 0;. É uma regra do guia desde a aula Variáveis.
3.5. O aviso que só aparece com -O2
No caso acima, a variável nunca recebe valor, e o gcc percebe de cara. Mas quando ela recebe valor às vezes, perceber exige uma análise mais funda do programa, que o gcc só faz quando otimiza (-O2, aula Compilar com gcc). Neste programa (o scanf lê um número do teclado e o switch escolhe um caso; aulas Entrada com scanf e switch), o desconto só recebe valor para os tipos 1 e 2:
#include <stdio.h>
int main(void) {
int tipo = 0;
if (scanf("%d", &tipo) != 1) {
return 1;
}
int desconto;
switch (tipo) {
case 1: desconto = 5; break;
case 2: desconto = 10; break;
}
printf("Desconto: %d%%\n", desconto);
return 0;
}
$ gcc -std=c23 -Wall -Wextra v1.c -o v1
$ « sem -O2: nenhum aviso
$ gcc -std=c23 -Wall -Wextra -O2 v1.c -o v1
In file included from /usr/include/stdio.h:974,
from v1.c:1:
In function ‘printf’,
inlined from ‘main’ at v1.c:13:5:
/usr/include/x86_64-linux-gnu/bits/stdio2.h:118:10: warning: ‘desconto’ may be used uninitialized [-Wmaybe-uninitialized]
118 | return __printf_chk (__USE_FORTIFY_LEVEL - 1, __fmt, __va_arg_pack ());
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
v1.c: In function ‘main’:
v1.c:8:9: note: ‘desconto’ was declared here
8 | int desconto;
| ^~~~~~~~
$ echo 1 | ./v1 « o echo … | digita o número para o programa
Desconto: 5%
$ echo 3 | ./v1
Desconto: 0% « tipo 3: não tem desconto, e saiu 0 por sorte
"desconto pode ser usada sem valor" (may be: em algum caminho, sim; aqui, no tipo 3). A mensagem assusta, porque começa dentro da biblioteca: com -O2, o gcc "colou" o código do printf dentro da main (inlined from ‘main’ at v1.c:13:5, "copiado para dentro da main, na linha 13") e reclamou lá dentro. Leia as partes que falam do seu arquivo: a linha 13 (o printf) e a note da linha 8 (onde a variável foi criada). E o 0%? Saiu por sorte: é o mesmo lixo da seção 3.4, que pode mudar com outro compilador ou outra opção. Por isso, de vez em quando, compile também com -O2, só para ver se aparecem avisos novos.
Conserto: int desconto = 0;. Com um valor inicial, todos os caminhos ficam cobertos.
3.6. Outros avisos que você vai encontrar
$ gcc -std=c23 -Wall -Wextra efeito.c -o efeito « total == 20;
efeito.c: In function ‘main’:
efeito.c:5:11: warning: statement with no effect [-Wunused-value]
5 | total == 20;
| ~~~~~~^~~~~
$ gcc -std=c23 -Wall -Wextra coment.c -o coment && ./coment « // fotos em C:\fotos\
coment.c: In function ‘main’:
coment.c:4:5: warning: multi-line comment [-Wcomment]
4 | // fotos em C:\fotos\
| ^
$ « o printf("Fotos salvas!\n") da linha 5 sumiu
$ gcc -std=c23 dobro.c -o dobro « sem -Wall: nada
$ gcc -std=c23 -Wall -Wextra dobro.c -o dobro
dobro.c: In function ‘dobro’:
dobro.c:7:1: warning: control reaches end of non-void function [-Wreturn-type]
7 | }
| ^
| Aviso (gcc) | Exemplo | O que quer dizer |
|---|---|---|
statement with no effect [-Wunused-value] | total == 20; | Uma comparação solta, que não faz nada. Provavelmente era total = 20;. (Clang: equality comparison result unused, e sugere o =.) |
multi-line comment [-Wcomment] | // C:\fotos\ | A barra invertida no fim do comentário "cola" a linha seguinte nele: o printf virou comentário (aula Comentários). |
control reaches end of non-void function [-Wreturn-type] | Uma função que promete devolver um número e, em algum caminho, não devolve | O resultado é lixo (aula Valor de Retorno). |
suggest braces around empty body in an ‘if’ statement [-Wempty-body] | if (nota >= 7); | Um ; logo depois do if: o bloco ficou vazio (aula Compilar com gcc). |
unused parameter [-Wunused-parameter] | int main(int argc, char *argv[]) sem usar | Parâmetro recebido e ignorado (só com -Wextra). |
4. Avisos que o gcc 15 já trata como erro
Alguns enganos eram só avisos nos compiladores antigos e, de tão perigosos, viraram erros a partir do gcc 14. Eles ainda mostram o nome de aviso entre colchetes, mas impedem o programa, mesmo sem -Wall:
| Nome | Quando acontece | Exemplo de mensagem |
|---|---|---|
[-Wimplicit-function-declaration] | Usar uma função sem o #include dela, ou com o nome errado | error: implicit declaration of function ‘printf’ |
[-Wint-conversion] | Misturar número e endereço (texto num int) | error: initialization of ‘int’ from ‘char *’ makes integer from pointer without a cast |
Os dois aparecem, com a mensagem real, na aula Lendo Erros do Compilador. Se um livro ou curso antigo disser que "é só um aviso", agora você sabe por que o seu gcc recusa.
5. -Werror: avisos viram erros
Com -Werror, todo aviso passa a ser tratado como erro, e o programa não é criado:
$ gcc -std=c23 -Wall -Wextra -Werror igual.c -o igual
igual.c: In function ‘main’:
igual.c:5:9: error: suggest parentheses around assignment used as truth value [-Werror=parentheses]
5 | if (nota = 10) {
| ^~~~
cc1: all warnings being treated as errors
$ echo $?
1
$ gcc -std=c23 -Wall -Wextra -Werror compras.c -o compras
compras.c: In function ‘main’:
compras.c:4:9: error: unused variable ‘itens’ [-Werror=unused-variable]
4 | int itens = 3;
| ^~~~~
cc1: all warnings being treated as errors
Repare: warning: virou error:, o nome entre colchetes virou [-Werror=…], e a última linha explica: "todos os avisos estão sendo tratados como erros" (o cc1 é a parte do gcc que compila C). O Clang marca assim: error: unused variable 'itens' [-Werror,-Wunused-variable].
Quando usar? Em projetos sérios, o -Werror costuma estar ligado no sistema de compilação (aulas Makefile e CMake) e nos servidores que testam cada mudança: ninguém consegue entregar código com aviso. Para quem está aprendendo, é uma ótima disciplina: ligue-o e o compilador não deixa você "deixar para depois". A missão final desta aula usa o -Werror.
Mais avisos: -Wconversion
-Wall -Wextra é o mínimo, não o máximo. Uma opção extra muito útil é a -Wconversion, que avisa quando um valor perde parte de si numa conversão. Aqui, 2,50 × 3 dá 7,50, e o int guarda só o 7:
$ gcc -std=c23 -Wall -Wextra conversao.c -o conversao && ./conversao « int total = preco * 3;
Total: 7 reais « sumiram 50 centavos, e nenhum aviso
$ gcc -std=c23 -Wall -Wextra -Wconversion conversao.c -o conversao
conversao.c: In function ‘main’:
conversao.c:5:17: warning: conversion from ‘double’ to ‘int’ may change value [-Wfloat-conversion]
5 | int total = preco * 3;
| ^~~~~
"A conversão de double para int pode mudar o valor". A aula Conversão de Tipos explica quando isso é de propósito. Outras opções que você vai ver em projetos: -Wpedantic (avisa o que não é C padrão) e -Wshadow (avisa quando um nome esconde outro, aula Escopo).
6. Por que nunca ignorar avisos
- Os avisos apontam bugs reais. Os exemplos da seção 3 compilavam e rodavam, e todos davam resultado errado.
- Avisos se acumulam. Um aviso "inofensivo" hoje vira dez amanhã, e o aviso importante se perde no meio deles. Com zero avisos, qualquer aviso novo salta aos olhos.
- O compilador conhece as armadilhas da linguagem. O C tem muitas, e os avisos são décadas de experiência resumidas.
- Corrigir na hora é barato. O mesmo engano, achado depois que o programa está nas mãos de alguém, custa muito mais.
Existe a opção -w (minúsculo), que desliga todos os avisos, até os do -Wall -Wextra:
$ gcc -std=c23 -Wall -Wextra -w igual.c -o igual $ « o aviso sumiu; o erro do programa continua lá
É apagar a luz do óleo em vez de pôr óleo. Não use. O conserto de um aviso é sempre mudar o código.
A regra do guia: compile sempre com -Wall -Wextra e só considere o programa pronto quando a compilação estiver em silêncio. As missões do editor muitas vezes exigem isso (a meta "sem avisos").
Quando dá errado
O que significa: muitas vezes, o compilador sabia. Você compilou sem -Wall -Wextra, ou viu o aviso e ignorou.
Como consertar: compile de novo com -Wall -Wextra (e, para garantir, com -O2 também) e leia cada warning:.
format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘double’
O que significa: a lacuna do printf não combina com o tipo do valor (seção 3.1). O que aparece na tela é lixo, e com %s o programa pode até cair (aula Saída com printf).
Como consertar: use a lacuna que o gcc sugere na última linha do desenho.
suggest parentheses around assignment used as truth value
O que significa: um = dentro de um if (ou while). Quase sempre era ==.
Como consertar: troque por ==.
comparison of integer expressions of different signedness
O que significa: você está comparando um número que aceita negativos com um que não aceita. Se o primeiro for negativo, o resultado sai errado.
Como consertar: use o mesmo tipo dos dois lados.
is used uninitialized / may be used uninitialized
O que significa: uma variável é lida antes de receber valor (sempre, ou em algum caminho).
Como consertar: dê um valor inicial na criação: int x = 0;.
cc1: all warnings being treated as errors
O que significa: o comando tem -Werror; um aviso impediu a criação do programa.
Como consertar: corrija o aviso indicado acima dessa linha. (Tirar o -Werror só esconde o problema.)
Referência rápida
| Opção | O que faz |
|---|---|
-Wall | Liga os avisos principais (sempre use) |
-Wextra | Liga avisos extras (sempre use) |
-O2 | Otimiza; de quebra, revela avisos como -Wmaybe-uninitialized |
-Werror | Trata avisos como erros: o programa não é criado |
-Wconversion | Avisa conversões que podem mudar o valor |
-w | Desliga todos os avisos (não use) |
| Aviso | Ligado por | Conserto típico |
|---|---|---|
format ‘%…’ expects argument of type… | sempre (e -Wall) | A lacuna do tipo certo |
unused variable | -Wall | Use a variável ou apague-a |
unused parameter | -Wextra | Tire o parâmetro ou use-o |
suggest parentheses around assignment | -Wall | = → == |
different signedness | -Wextra (no C) | Mesmo tipo dos dois lados |
is used uninitialized | -Wall | Valor inicial: int x = 0; |
may be used uninitialized | -Wall + -O2 | Valor inicial: int x = 0; |
statement with no effect | -Wall | Provavelmente == → = |
control reaches end of non-void function | -Wall | Um return em todos os caminhos |
conversion … may change value | -Wconversion | Tipo certo, ou conversão de propósito |
Exercícios
1. Ligar os avisos
Complete o comando padrão do guia:
2. Avisos como erros
Que opção faz qualquer aviso impedir a criação do programa?
3. Corrija a condição
Complete para comparar, e não guardar:
4. O que acontece quando a compilação dá só um warning:?
5. Por que if (saldo < limite), com saldo = -1 (int) e limite = 10 (unsigned), deu falso?
6. Com printf("%d\n", 1.65);, o que acontece?
7. Qual é a forma certa de lidar com um aviso?
Missão final: zero avisos (com -Werror)
Missão: esta caixa compila com -Werror: com qualquer aviso, o programa nem é criado. Corrija o código da lojinha (sem tirar o -Werror!) até ele compilar e mostrar:
Estoque da lojinha Canetas: 0 Repor canetas!
Dicas: uma variável sobrando, uma variável sem valor (as canetas começam em 0) e um = que deveria ser ==. Conserte um de cada vez, rodando entre um e outro.
#include <stdio.h>
int main(void) {
int cadernos = 12;
int canetas;
printf("Estoque da lojinha\n");
printf("Canetas: %d\n", canetas);
if (canetas = 0) {
printf("Repor canetas!\n");
}
return 0;
}
#include <stdio.h>
int main(void) {
int canetas = 0;
printf("Estoque da lojinha\n");
printf("Canetas: %d\n", canetas);
if (canetas == 0) {
printf("Repor canetas!\n");
}
return 0;
}
Resumo
- Um aviso (
warning:) não impede a criação do programa, mas quase sempre aponta um engano real. - O
gccvem com quase todos os avisos desligados.-Wall -Wextraos ligam: use sempre. Em C, alguns importantes (como o-Wsign-compare) só vêm com o-Wextra. - Avisos que salvam programas: formato errado no
printf,=no lugar de==,intcomparado comunsigned, variável sem valor, variável não usada. - Alguns avisos (
may be used uninitialized) só aparecem com-O2: compile com ele de vez em quando. - No gcc 15,
implicit declaration of functioneint-conversionjá são erros. -Werrortransforma avisos em erros;-Wconversionliga mais avisos;-wesconde todos (não use).- A meta é zero avisos: o conserto é sempre mudar o código.
- Próximo passo: Variáveis, onde começam os programas que guardam e mudam valores.