Uma variável é um pedaço nomeado de memória que guarda um valor que o seu programa pode ler e mudar. Em C você sempre diz de antemão que tipo de valor ela guarda, e essa escolha é permanente pela vida da variável.
Declarando uma variável
A forma é tipo, nome, ponto e vírgula:
int age;
double price;
char grade;
Cada linha reserva memória suficiente para aquele tipo de dado e prende um nome a ela. Nada foi guardado ainda - o espaço existe, mas o conteúdo dele é o que quer que tenha ficado ali de quem rodou antes.
Você pode dar um valor no mesmo momento, o que se chama inicialização:
Repare nos especificadores de formato: %d para int, %f para double, %c para char. O printf não inspeciona os valores que recebe - ele confia na sua string de formato, então uma incompatibilidade imprime besteira em vez de um erro.
Atribuição depois da declaração
Uma vez que a variável existe, você a muda com =:
O = em C é atribuição, não igualdade. score = score + 10 se lê como "pegue o que está em score, some 10, ponha o resultado de volta em score". O operador de comparação é ==, e confundir os dois é um bug tão comum que tem uma seção própria na página de booleanos.
O atalho score += 10 faz a mesma coisa com menos caracteres; os operadores de atribuição composta cobrem toda a aritmética.
A armadilha da variável não inicializada
Esse é, de longe, o bug de iniciante mais comum em C, e ele não produz um erro:
Rode. Você pode ver 15, que é a resposta certa. Pode ver um número aleatório enorme. Pode ver algo diferente numa segunda execução ou noutra máquina. Tudo isso é comportamento "correto", porque ler uma variável local não inicializada é comportamento indefinido - a norma do C não impõe requisito nenhum sobre o que acontece.
Ao contrário de muitas linguagens, o C não zera as suas locais. Uma variável local é uma fatia da pilha, e a pilha está cheia de sobras de chamadas de função anteriores. Às vezes essas sobras por acaso são zero, e é isso que torna esse bug tão perigoso: ele muitas vezes funciona nos testes e falha em produção.
A correção é um caractere:
Faça disso um hábito: inicialize toda variável no ponto da declaração. Se você genuinamente ainda não tem um valor sensato, 0 ou NULL é melhor que lixo. E compile com -Wall, que pega a maioria dos casos:
warning: 'total' is used uninitialized in this function
Variáveis globais e static são a exceção - elas são inicializadas com zero automaticamente. Contar com isso tudo bem, mas escrever = 0 mesmo assim documenta a sua intenção.
Declarando várias de uma vez
Variáveis do mesmo tipo podem compartilhar uma declaração, com ou sem inicializadores:
Isso é legal e comum para valores bem relacionados como x, y, z. É também onde mora uma leitura equivocada clássica:
int a = 0, b = 0, c = 0; /* os tres sao 0 */
int d, e, f = 0; /* so f e 0 - d e e sao lixo */
O inicializador se prende a um nome, não à linha. Quando os valores diferem em significado, dê a cada um a sua própria linha - lê melhor e aparece melhor nos diffs.
Declarar ponteiros numa linha só tem a mesma armadilha, de forma mais aguda:
int *p, q; /* p e um ponteiro para int; q e um int comum */
O * se prende ao nome, não ao tipo. Declare ponteiros um por linha.
Regras e convenções de nomes
As regras do compilador:
- Apenas letras, dígitos e sublinhados.
- Não pode começar com dígito:
total2tudo bem,2totalnão. - Não pode ser uma palavra-chave do C: nada de variável chamada
int,return,for,double. - Distingue maiúsculas de minúsculas:
count,CounteCOUNTsão três variáveis distintas. - Nomes começando com sublinhado, ou contendo sublinhado duplo, são reservados para a implementação. Não os crie.
int itemCount; /* legal */
int item_count; /* legal - o estilo usual do C */
int _count; /* legal, mas reservado - evite */
int item-count; /* erro: '-' e o operador de subtracao */
int 3rd_place; /* erro: comeca com um digito */
int float; /* erro: palavra-chave */
As convenções que a maior parte do código C segue: snake_case para variáveis e funções, MAIUSCULAS para constantes de macro, e nomes que dizem o que o valor significa em vez de qual o tipo dele. elapsed_ms é melhor que t; customer_count é melhor que n2.
Nomes curtos continuam válidos onde o escopo é minúsculo - i como contador de laço é universalmente entendido, e ninguém quer for (int indice_de_iteracao_do_laco = 0; ...).
Onde uma variável vive
Onde você declara uma variável determina quem consegue vê-la e quanto tempo ela dura. Isso é escopo, e a versão curta é:
Uma variável é visível da sua declaração até a chave de fechamento do bloco que a contém. Globais vivem pelo programa inteiro e são visíveis em todo lugar, o que soa conveniente e é a razão de darem problema: qualquer função pode mudar uma, então descobrir quem mudou vira uma busca pelo arquivo inteiro. Prefira locais e passe valores às funções como parâmetros.
Declarando em qualquer lugar (C99 e posteriores)
No C89 original, toda declaração tinha que vir antes de qualquer instrução num bloco:
int main(void) {
int i, sum = 0; /* todas as declaracoes primeiro */
printf("Comecando\n");
for (i = 0; i < 10; i++) { sum += i; }
return 0;
}
Desde o C99 você pode declarar onde precisa do valor pela primeira vez, inclusive no cabeçalho do for:
Esse é o melhor estilo: a declaração fica ao lado do primeiro uso, e o i não pode vazar para o resto da função. Compile com -std=c17 (ou qualquer configuração C99+) e funciona em todo lugar.
Perguntas frequentes
Como se declara uma variável em C?
Escreva o tipo, depois o nome, depois um ponto e vírgula: int idade;. Você pode dar um valor ao mesmo tempo - int idade = 30; - o que se chama inicialização e é quase sempre o que você quer.
Qual a diferença entre declarar e inicializar uma variável?
Declarar reserva o espaço e lhe dá um nome (int count;). Inicializar coloca um valor nele no momento da criação (int count = 0;). Uma variável local declarada mas não inicializada contém os bytes que já estavam naquele endereço - lê-la é comportamento indefinido.
Quais são as regras para nomes de variáveis em C?
Apenas letras, dígitos e sublinhados; não pode começar com dígito; não pode ser uma palavra-chave como int ou for; e há distinção entre maiúsculas e minúsculas, então total e Total são variáveis diferentes. Nomes começando com sublinhado são reservados - evite-os.
Dá para declarar variáveis em qualquer ponto de uma função em C?
Desde o C99, sim - declare cada variável exatamente onde precisar dela pela primeira vez. No C89 original toda declaração precisava aparecer no topo de um bloco, e é por isso que código antigo tem um paredão de declarações antes de qualquer trabalho de verdade.