C tem muito pouca sintaxe para aprender - cerca de 32 palavras-chave e um punhado de regras de pontuação. Quase todo programa que você vai escrever tem a mesma forma externa, então vale a pena desmontar essa forma uma vez e com cuidado.
O menor programa completo
Isto compila, executa e não faz nada:
Sem includes, sem saída, sem classe ou módulo de cerimônia. main é o ponto de entrada: quando o sistema operacional inicia seu programa, ele chama main. Quando main retorna, o programa termina, e o valor retornado é o código de saída.
Adicione saída e você precisa de um include:
Diretivas de pré-processador
Linhas que começam com # são tratadas antes da compilação propriamente dita, pelo pré-processador. Elas não são instruções C, e não levam ponto e vírgula.
#include <stdio.h> /* cabeçalho da biblioteca padrão - colchetes angulares */
#include "myutils.h" /* seu próprio cabeçalho - aspas, procurado localmente primeiro */
#define MAX 100 /* uma macro - MAX é substituído por 100 em todo o resto */
#include é uma colagem literal de texto: o conteúdo inteiro do arquivo nomeado é despejado ali naquele ponto. stdio.h contém a declaração de printf, que é como o compilador sabe que argumentos printf recebe. Deixe o include de fora e você recebe implicit declaration of function 'printf'.
A distinção entre colchetes angulares e aspas é sobre onde o compilador procura: <...> significa os diretórios de include do sistema, "..." significa olhar ao lado deste arquivo primeiro.
A função main
int main(void) {
return 0;
}
Quatro partes, cada uma com significado:
int- o tipo de retorno da main. O valor vai para o sistema operacional como código de saída, em que 0 significa sucesso.main- o nome reservado que o runtime chama. Todo programa C hospedado tem exatamente um.(void)- a lista de parâmetros.voidaqui significa "não recebe argumentos". Escrevermain()em vez disso é válido, mas mais fraco: parênteses vazios em C significam "parâmetros não especificados", o que desativa a verificação de argumentos.{ ... }- o corpo da função.
A outra forma padrão recebe argumentos de linha de comando:
int main(int argc, char *argv[]) { ... }
Use int main(void) até precisar deles.
Instruções e ponto e vírgula
Uma instrução é uma única ordem, e termina com ponto e vírgula.
Quatro instruções, quatro pontos e vírgulas. O ponto e vírgula é um terminador, não um separador - a última instrução de um bloco também precisa de um.
O que não leva ponto e vírgula:
#include <stdio.h> /* linha de pré-processador - sem ponto e vírgula */
int add(int a, int b) { /* cabeçalho de definição de função - sem ponto e vírgula */
return a + b;
} /* chave de fechamento de uma função - sem ponto e vírgula */
if (x > 0) {
...
} /* chave de fechamento de um bloco de controle - sem ponto e vírgula */
O caso que pega todo mundo é um ponto e vírgula onde deveria haver um corpo:
if (score > 90); /* BUG: este ; é o corpo inteiro do if */
printf("Excelente!\n"); /* sempre executa, qualquer que seja score */
Isso é C perfeitamente válido. O if controla uma instrução vazia, e o printf é apenas a próxima linha na sequência. -Wall avisa sobre isso; o compilador não vai te impedir.
Blocos e chaves
Chaves agrupam instruções em um bloco, que conta como uma única instrução onde quer que uma instrução seja esperada.
As chaves são opcionais quando o corpo é uma única instrução, mas omiti-las é como acontecem os bugs famosos - adicione uma segunda linha depois e ela silenciosamente fica fora do if. Use chaves sempre.
Blocos também criam escopo: uma variável declarada dentro de { ... } deixa de existir na chave de fechamento.
Sensibilidade a maiúsculas e espaços em branco
C diferencia maiúsculas de minúsculas em todo lugar. total, Total e TOTAL são três nomes distintos. Toda palavra-chave é minúscula, então Int, Return e Printf são todos erros - e a mensagem de erro para Printf é confusa, porque o compilador supõe que você quis dizer alguma função de que ele nunca ouviu falar.
Espaços em branco, em contraste, são quase inteiramente livres. O compilador trata qualquer sequência de espaços, tabulações e quebras de linha como um único separador. Isto é válido:
int main ( void )
{
printf
( "Hello\n" ) ;
return 0 ;
}
Isto também:
int main(void){printf("Hello\n");return 0;}
Ambos compilam de forma idêntica. Já que o compilador não se importa, a formatação é inteiramente para humanos - e o layout convencional (uma instrução por linha, quatro espaços ou uma tabulação por nível de aninhamento, chave de abertura na mesma linha) vale ser seguido porque toda base de código C que você ler vai usar algo próximo disso.
Dois lugares em que o espaço em branco importa: você não pode partir uma palavra-chave ou um identificador (in t não é int), e não pode colocar uma quebra de linha dentro de um literal de string comum.
Identificadores: regras de nomenclatura
Um identificador é qualquer nome que você escolhe - variáveis, funções, tipos. As regras:
- Formados por letras, dígitos e sublinhados.
- Não podem começar com um dígito.
total2está ok,2totalnão. - Não podem ser uma palavra-chave: nada de variável chamada
int,foroureturn. - Maiúsculas importam.
- Nomes que começam com sublinhado, e qualquer coisa com dois sublinhados seguidos, são reservados para a implementação - não invente esses.
int score; /* bom */
int total_items; /* bom - snake_case é a convenção do C */
int _hidden; /* válido mas reservado - evite */
int 2fast; /* erro */
int float; /* erro - palavra-chave */
Um programa totalmente comentado
Tudo acima, em um só lugar:
A ordem de leitura importa aqui: with_tax é definida antes de main usá-la. C lê o arquivo de cima para baixo, então uma função precisa ser declarada antes de ser chamada. Defina-a mais cedo, ou escreva um protótipo de função no topo e defina-a depois.
Perguntas frequentes
Qual é a estrutura básica de um programa em C?
Primeiro as diretivas de pré-processador (#include <stdio.h>), depois as definições de função, uma das quais precisa ser main. Dentro de uma função, as instruções terminam com ponto e vírgula e os blocos ficam entre chaves. Um programa mínimo é #include <stdio.h> mais int main(void) { return 0; }.
Por que é int main(void) e não apenas main()?
int é o tipo de retorno da main - o código de saída que o programa devolve ao sistema operacional. (void) diz explicitamente que main não recebe argumentos. Escrever main() com parênteses vazios é um estilo antigo que não diz nada ao compilador sobre os parâmetros, então ele verifica menos coisas.
Todas as instruções em C precisam de ponto e vírgula?
Toda instrução precisa, mas nem toda linha. Diretivas de pré-processador (#include, #define), definições de função e a chave de fechamento de um bloco ou de um if/for/while não levam. Um ponto e vírgula solto depois de if (x) é C válido e silenciosamente faz o corpo executar incondicionalmente.
C diferencia maiúsculas de minúsculas?
Sim, completamente. count, Count e COUNT são três identificadores diferentes, e Int não é a palavra-chave int. Toda palavra-chave do C é minúscula, então uma letra maiúscula em Return ou Printf produz um erro.