Local, global, de bloco e static — onde uma variável existe e por quanto tempo
Toda variável em C tem um escopo: a região do código onde ela existe e pode ser acessada. Fora desse escopo, a variável simplesmente não existe — tentar usá-la gera erro de compilação.
{ } e pela posição no arquivo.
C reconhece quatro categorias de escopo:
| Tipo de escopo | Onde é declarado | Visível de | Dura até |
|---|---|---|---|
| De bloco (local) | Dentro de { } |
Ponto da declaração | Fim do bloco } |
| De parâmetro | Lista de parâmetros da função | Início do corpo da função | Fim da função } |
| De arquivo (global) | Fora de qualquer função | Ponto da declaração até fim do arquivo | Fim do programa |
Local static |
Dentro de função, com static |
Apenas dentro da função | Fim do programa (persiste entre chamadas) |
Uma variável declarada dentro de um par de chaves { } é local àquele bloco. Ela nasce quando o programa entra no bloco e morre quando sai.
#include <stdio.h>
void exemploLocal() {
int x = 10; // x existe apenas dentro de exemploLocal
if (x > 5) {
int y = 20; // y existe apenas dentro deste if
printf("x=%d y=%d\n", x, y); // OK: x e y visíveis aqui
}
// printf("%d", y); // ❌ ERRO: y não existe mais aqui
printf("x=%d\n", x); // OK: x ainda existe aqui
} // x é destruída ao sair de exemploLocal
int main() {
exemploLocal();
// printf("%d", x); // ❌ ERRO: x não existe em main
return 0;
}
for (C99)Declarar a variável de controle dentro do próprio for limita seu escopo ao bloco do loop — uma boa prática:
for (int i = 0; i < 5; i++) {
printf("%d ", i); // OK: i existe dentro do for
}
// printf("%d", i); // ❌ ERRO: i não existe fora do for (C99)
int x; // ❌ contém lixo — valor imprevisível printf("%d\n", x); // comportamento indefinido! int y = 0; // ✅ sempre inicialize antes de usar
Uma variável declarada fora de qualquer função — normalmente no topo do arquivo — é global. Ela é visível em todas as funções do arquivo e existe durante toda a execução do programa.
#include <stdio.h> int contador = 0; // global — visível em todas as funções const float TAXA = 0.05f; // constante global — uso adequado void incrementar() { contador++; // acessa e modifica a global diretamente } void exibir() { printf("Contador: %d | Taxa: %.0f%%\n", contador, TAXA * 100); } int main() { exibir(); // Contador: 0 | Taxa: 5% incrementar(); incrementar(); incrementar(); exibir(); // Contador: 3 | Taxa: 5% return 0; }
Ao contrário das locais, variáveis globais são sempre zeradas antes do programa começar:
| Tipo | Valor padrão (global) |
|---|---|
int | 0 |
float / double | 0.0 |
char | '\0' |
| Ponteiro | NULL |
Quando uma variável local tem o mesmo nome de uma variável global, a local sombreia (esconde) a global dentro do seu escopo. A global continua existindo, mas fica temporariamente inacessível pelo nome.
#include <stdio.h> int valor = 100; // global void demonstrar() { printf("global: %d\n", valor); // 100 — ainda sem sombra int valor = 50; // local — cria sombra sobre a global printf("local: %d\n", valor); // 50 { int valor = 25; // bloco interno — sombra da sombra printf("bloco: %d\n", valor); // 25 } printf("local: %d\n", valor); // 50 — volta ao escopo local } int main() { demonstrar(); printf("global: %d\n", valor); // 100 — global intocada return 0; }
gcc -Wall -Wshadow para receber avisos do compilador sempre que houver sombreamento no seu código.
| ✅ Quando globais fazem sentido | ❌ Quando globais causam problemas |
|---|---|
Constantes imutáveis (const) compartilhadas por todo o programa |
Variáveis que podem ser modificadas por qualquer função |
| Contadores ou flags de estado do programa inteiro | Variáveis com nomes genéricos (i, temp, aux) |
| Tabelas de configuração apenas de leitura | Variáveis usadas para evitar passar parâmetros |
| Programas pequenos e de arquivo único | Projetos com múltiplos arquivos e equipes |
int resultado; // global desnecessária void somar(int a, int b) { resultado = a + b; // qualquer função pode corromper isso }
int somar(int a, int b) {
return a + b; // limpo, sem efeitos colaterais
}
static — Persistindo Entre ChamadasC tem um tipo especial de variável local: a variável local static. Ela tem escopo local (só visível dentro da função) mas duração global — não é destruída ao retornar e persiste entre chamadas.
static é inicializada uma única vez (na primeira execução da função) e mantém seu valor entre chamadas consecutivas — como uma "memória privada" daquela função.
#include <stdio.h>
void contarChamadas() {
static int n = 0; // inicializada UMA vez; persiste entre chamadas
n++;
printf("Esta função foi chamada %d vez(es)\n", n);
}
int main() {
contarChamadas(); // Esta função foi chamada 1 vez(es)
contarChamadas(); // Esta função foi chamada 2 vez(es)
contarChamadas(); // Esta função foi chamada 3 vez(es)
return 0;
}
static vs global| Característica | Local normal | Local static |
Global |
|---|---|---|---|
| Visibilidade | Apenas dentro da função | Apenas dentro da função | Todo o arquivo |
| Inicialização automática | ❌ Contém lixo | ✅ Zero (uma vez) | ✅ Zero |
| Persiste entre chamadas? | ❌ Destruída ao retornar | ✅ Sim | ✅ Sim |
| Armazenamento | Stack (pilha) | Segmento de dados | Segmento de dados |
#include <stdio.h>
int gerarID() {
static int proximoID = 1000; // começa em 1000, nunca reinicia
return proximoID++;
}
int main() {
printf("ID: %d\n", gerarID()); // ID: 1000
printf("ID: %d\n", gerarID()); // ID: 1001
printf("ID: %d\n", gerarID()); // ID: 1002
return 0;
}
static local: Geradores de IDs únicos, contadores de chamadas, buffers de cache — tudo isso sem expor a variável como global.
Os parâmetros de uma função têm escopo equivalente ao de variáveis locais declaradas no início do corpo. Eles existem enquanto a função está executando e são destruídos ao retornar.
#include <stdio.h>
void processar(int valor, float taxa) {
// 'valor' e 'taxa' existem aqui — escopo idêntico ao de locais
valor = valor + (int)(valor * taxa); // modifica a cópia local
printf("Valor processado: %d\n", valor);
} // 'valor' e 'taxa' são destruídos aqui
int main() {
int preco = 100;
processar(preco, 0.1f);
printf("Preço original: %d\n", preco); // 100 — intocado
return 0;
}
#include <stdio.h> /* ── ESCOPO GLOBAL ─────────────────────────────── */ int totalVendas = 0; // global: visível em todo o arquivo const float IMPOSTO = 0.12f; // constante global: uso adequado float calcularPrecoFinal(float preco, int quantidade) { /* ── ESCOPO DE PARÂMETRO ────────────────── */ // 'preco' e 'quantidade' existem apenas aqui /* ── ESCOPO LOCAL (bloco da função) ────── */ float subtotal = preco * quantidade; float imposto = subtotal * IMPOSTO; // usa constante global float total = subtotal + imposto; /* ── STATIC LOCAL ───────────────────────── */ static int numTransacoes = 0; // persiste entre chamadas numTransacoes++; /* ── ESCOPO DE BLOCO (if interno) ───────── */ if (total > 500.0f) { float desconto = total * 0.05f; // existe apenas neste if total -= desconto; printf(" Desconto de 5%% aplicado: -R$%.2f\n", desconto); } // 'desconto' destruída aqui totalVendas++; // modifica global printf(" Transacao #%d | Total: R$%.2f\n", numTransacoes, total); return total; } int main() { printf("=== Caixa da Loja ===\n"); calcularPrecoFinal(80.0f, 3); // 3 x R$80 = R$240 + imposto calcularPrecoFinal(200.0f, 4); // 4 x R$200 = R$800 -> desconto! calcularPrecoFinal(50.0f, 2); // 2 x R$50 = R$100 + imposto printf("\nTotal de vendas no sistema: %d\n", totalVendas); return 0; }
| Aspecto | C | Java |
|---|---|---|
| Local não inicializada | ⚠️ Contém lixo — comportamento indefinido | ✅ Erro de compilação se usada sem inicializar |
| Variável global | Declarada fora de qualquer função | Não existe — substituída por atributos static de classe |
| Inicialização automática | Apenas globais e static locais (com zero) |
Atributos de objetos são zerados automaticamente |
Variável de controle do for |
Morre fora do for (C99) |
Morre fora do for — igual ao C |
| Sombreamento | Permitido (com aviso -Wshadow) |
Permitido para locais, mas não para atributos de instância |
Local static |
✅ Existe — persiste entre chamadas | ❌ Não existe — sem equivalente direto |
int contador = 0;
void incrementar() {
contador++;
}
int obter() {
return contador;
}
class Contador {
static int valor = 0;
static void incrementar() {
valor++;
}
static int obter() {
return valor;
}
}