Guia de Estilo para C
Não existe uma única maneira correta de estilizar código. Mas há com certeza muitas maneiras erradas (ou, pelo menos, ruins). Mesmo assim, o CS50 pede que você siga as convenções abaixo para que possamos analisar de forma confiável o estilo do seu código. Da mesma forma, as empresas costumam adotar suas próprias convenções de estilo para toda a empresa.
Comprimento da Linha
Por convenção, o comprimento máximo de uma linha de código é de 80 caracteres em C, que é historicamente baseado em monitores de tamanho padrão em terminais de computador mais antigos, que podiam exibir 24 linhas verticalmente e 80 caracteres horizontalmente. Embora a tecnologia moderna tenha tornado obsoleta a necessidade de manter as linhas com até 80 caracteres, ela ainda é uma orientação que deve ser considerada um "soft stop" e uma linha de 100 caracteres deve realmente ser o máximo que você escreve em C, caso contrário, os leitores geralmente precisarão rolar para baixo. Se você precisar de mais de 100 caracteres, pode ser hora de repensar seus nomes de variáveis ou seu design geral!
// Estas próximas linhas de código primeiro solicitam ao usuário que forneça dois valores inteiros e então multiplicam esses dois valores inteiros, para que possam ser usados mais tarde no programa
int primeiro_valor_inteiro_coletado_do_usuario = get_int("Inteiro, por favor: ");
int segundo_valor_inteiro_coletado_do_usuario = get_int("Outro inteiro, por favor: ");
int produto_dos_dois_valores_inteiros_do_usuario = primeiro_valor_inteiro_coletado_do_usuario * segundo_valor_inteiro_coletado_do_usuario;
Em outras linguagens, particularmente JavaScript, é significativamente mais difícil restringir linhas a um comprimento máximo; lá, seu objetivo deve ser quebrar linhas (como via \n
) em locais que maximizem a legibilidade e a clareza.
Comentários
Os comentários tornam o código mais legível, não apenas para outros (por exemplo, seu TF), mas também para você, especialmente quando horas, dias, semanas, meses ou anos se passam entre escrever e ler seu próprio código. Comentar muito pouco é ruim. Comentar muito é ruim. Onde está o ponto ideal? Comentar cada poucas linhas de código (ou seja, blocos interessantes) é uma orientação decente. Tente escrever comentários que abordem uma ou ambas as seguintes questões:
- O que este bloco faz?
- Por que implementei este bloco desta forma?
Dentro das funções, use "comentários embutidos" e mantenha-os curtos (por exemplo, uma linha), caso contrário, torna-se difícil distinguir os comentários do código, mesmo com realce de sintaxe. Coloque o comentário acima da(s) linha(s) à(s) qual(is) ele se aplica. Não há necessidade de escrever frases completas, mas capitalize a primeira palavra do comentário (a menos que seja o nome de uma função, variável ou algo parecido) e deixe um espaço entre //
e o primeiro caractere do seu comentário, como em:
// Converte Fahrenheit em Celsius
float c = 5.0 / 9.0 * (f - 32.0);
Em outras palavras, não faça isso:
//converte Fahrenheit em Celsius
float c = 5.0 / 9.0 * (f - 32.0);
Ou isso:
// converte Fahrenheit em Celsius
float c = 5.0 / 9.0 * (f - 32.0);
Ou isso:
float c = 5.0 / 9.0 * (f - 32.0); // Converte Fahrenheit em Celsius
Acima de seus arquivos .c e .h deve haver um comentário que resuma o que seu programa (ou aquele arquivo em particular) faz, como em:
// Diz olá para o mundo
Acima de cada uma de suas funções (exceto, talvez, main
), por outro lado, deve haver um comentário que resuma o que sua função está fazendo, como em:
// Retorna o quadrado de n
int quadrado(int n)
{
return n * n;
}
Cabeçalhos de Bibliotecas
Todos os cabeçalhos de biblioteca que você incluir devem ser listados em ordem alfabética, como em:
#include <cs50.h>
#include <stdio.h>
#include <string.h>
Isso torna mais fácil ver rapidamente, especialmente em uma lista longa, se você incluiu um cabeçalho.
Condições
As condições devem ser estilizadas da seguinte forma:
if (x > 0)
{
printf("x é positivo\n");
}
else if (x < 0)
{
printf("x é negativo\n");
}
else
{
printf("x é zero\n");
}
Observe como:
- as chaves se alinham bem, cada uma em sua própria linha, deixando perfeitamente claro o que está dentro da ramificação;
- há um único espaço após cada
if
; - cada chamada para
printf
é recuada com 4 espaços; - há espaços simples ao redor de
>
e ao redor de<
; e - não há nenhum espaço imediatamente após cada
(
ou imediatamente antes de cada)
.
Para economizar espaço, alguns programadores gostam de manter a primeira chave na mesma linha que a própria condição, mas não recomendamos, pois é mais difícil de ler, então não faça isso:
if (x < 0) {
printf("x é negativo\n");
} else if (x < 0) {
printf("x é negativo\n");
}
E definitivamente não faça isso:
if (x < 0)
{
printf("x é negativo\n");
}
else
{
printf("x é negativo\n");
}
Chaves
Declare uma escolha
do seguinte modo:
switch (n)
{
case -1:
printf("n é -1\n");
break;
case 1:
printf("n é 1\n");
break;
default:
printf("n não é -1 nem 1\n");
break;
}
Observe como:
- cada chave está em uma linha separada;
- há um único espaço após
switch
; - não há nenhum espaço imediatamente após cada
(
ou imediatamente antes de cada)
; - os casos da chave são recuados com 4 espaços;
- os corpos dos casos são recuados ainda mais com 4 espaços; e
- cada
caso
(incluindopadrão
) termina com umbreak
.
Funções
De acordo com o C99, certifique-se de declarar main
com:
int main(void)
{
}
ou, se usar a Biblioteca CS50, com:
#include <cs50.h>
int main(int argc, string argv[])
{
}
ou com:
int main(int argc, char *argv[])
{
}
ou mesmo com:
int main(int argc, char **argv)
{
}
Não declare main
com:
int main()
{
}
ou com:
void main()
{
}
ou com:
main()
{
}
Quanto às suas próprias funções, certifique-se de defini-las de forma semelhante, com cada chave em sua própria linha e com o tipo de retorno na mesma linha que o nome da função, assim como fizemos com main
.
Identar
Identem seu código quatro espaços por vez para deixar claro quais blocos de código estão dentro de outros. Se você usar a tecla Tab do seu teclado para fazer isso, certifique-se de que o editor de texto esteja configurado para converter tabulações (\t
) em quatro espaços, caso contrário, seu código pode não ser impresso ou exibido corretamente no computador de outra pessoa, pois \t
é renderizado de forma diferente em diferentes editores. (Se usar o CS50 IDE, não há problema em usar Tab para identar, em vez de pressionar a barra de espaço do seu teclado repetidamente, pois pré-configuramos para converter \t
em quatro espaços.)
Aqui está um código bem identado:
// Imprime argumentos de linha de comando um por linha
printf("\n");
for (int i = 0; i < argc; i++)
{
for (int j = 0, n = strlen(argv[i]); j < n; j++)
{
printf("%c\n", argv[i][j]);
}
Loops
for
Sempre que você precisar de variáveis temporárias para iteração, use i
, depois j
, depois k
, a menos que nomes mais específicos tornem o seu código mais legível:
for (int i = 0; i < LIMIT; i++)
{
for (int j = 0; j < LIMIT; j++)
{
for (int k = 0; k < LIMIT; k++)
{
// Faça algo
}
}
}
Se você precisar de mais de três variáveis para iteração, talvez seja hora de repensar seu design!
while
Declare laços while
da seguinte forma:
while (condição)
{
// Faça algo
}
Observe como:
- cada chave está em sua própria linha;
- há um único espaço após
while
; - não há nenhum espaço imediatamente após o
(
ou imediatamente antes do)
; e - o corpo do laço (um comentário neste caso) é recuado com 4 espaços.
do … while
Declare laços do ... while
da seguinte forma:
do
{
// Faça algo
}
while (condição);
Observe como:
- cada chave está em sua própria linha;
- há um único espaço após
while
; - não há nenhum espaço imediatamente após o
(
ou imediatamente antes do)
; e - o corpo do laço (um comentário neste caso) é recuado com 4 espaços.
Ponteiros
Ao declarar um ponteiro, escreva o *
ao lado da variável, como em:
int *p;
Não escreva ao lado do tipo, como em:
int* p;
Variáveis
Como o CS50 usa C99, não defina todas as suas variáveis no topo de suas funções, mas sim quando e onde você realmente precisa delas. Além disso, restrinja o escopo de suas variáveis o máximo possível. Por exemplo, se i
for necessário apenas para um laço, declare i
dentro do próprio laço:
for (int i = 0; i < LIMIT; i++)
{
printf("%i\n", i);
}
Embora seja normal usar variáveis como i
, j
e k
para iteração, a maioria de suas variáveis deve ter nomes mais específicos. Se você está somando alguns valores, por exemplo, chame sua variável de soma
. Se o nome da sua variável justificar duas palavras (por exemplo, está_pronto
), coloque um sublinhado entre elas, uma convenção popular em C, embora menos em outras linguagens.
Se declarar várias variáveis do mesmo tipo de uma vez, é correto declará-las juntas, como em:
int quartos, moedas_de_dez_centavos, moedas_de_cinco_centavos, centavos;
Apenas não inicialize algumas, mas não outras, como em:
int quartos, moedas_de_dez_centavos = 0, moedas_de_cinco_centavos = 0 , centavos;
Também tome cuidado para declarar ponteiros separadamente de não ponteiros, como em:
int *p;
int n;
Não declare ponteiros na mesma linha que não ponteiros, como em:
int *p, n;
Estruturas
Declare uma struct
como um tipo da seguinte forma, com cada chave em sua própria linha e membros recuados nela, com o nome do tipo também em sua própria linha:
typedef struct
{
string nome;
string dormitório;
}
aluno;
Se a struct
contiver como membro um ponteiro para outra struct
, declare a struct
como tendo um nome idêntico ao tipo, sem usar sublinhados:
typedef struct nó
{
int n;
struct nó *próximo;
}
nó;