4.6 KiB
Curso Básico da Linguagem C
Variáveis e ponteiros
- Variáveis são elementos da linguagem que representam dados na memória.
- Ponteiros são variáveis que representam endereços de dados na memória.
Declaração e definição
Variáveis precisam ser declaradas e definidas antes de serem utilizadas.
Exemplo (var1.c
):
#include <stdio.h>
int main(void) {
int a = 10; /* Variável declarada e inicializada (definida). */
int b; /* Variável declarada, mas não inicializada! */
printf("a = %d\n", a);
printf("b = %d\n", b);
printf("a + b = %d\n", a + b);
return 0;
}
Compilando e executando:
:~$ gcc -o var1 var1.c :~$ ./var1 a = 10 b = 361680176 a + b = 361680186
Observe:
- A compilação não emitiu avisos e nem terminou com erro.
- A variável
b
(não inicializada) avaliou um valor qualquer.
Por que isso aconteceu?
Ao ser declarada, a variável recebeu um endereço e um tipo (int
). Como não
foi inicializada, seu valor será o que quer que esteja nos 4 bytes da
memória a partir do endereço designado para b
.
Por exemplo:
a -> 0x7ffd45c33fdc: 0a 00 00 00 (10) b -> 0x7ffd45c33fd8: 3a cd 8e 15 (361680176) <-- LIXO!
Como evitar esse erro?
A primeira (e mais óbvia) opção é não se esquecer de atribuir um valor à variável antes de usá-la, mas a compilação poderia ter sido feita com as opções de avisos:
-Wall
: Habilita todos os avisos sobre problemas evitáveis no código.-Wextra
: Habilita avisos adicionais.-Werror
: Trata todos os avisos como erros fatais.
Exemplo:
:~$ gcc -o var1 var1.c -Wall -Wextra -Werror var1.c: In function ‘main’: var1.c:10:5: error: ‘b’ is used uninitialized [-Werror=uninitialized] 10 | printf("b = %d\n", b); | ^~~~~~~~~~~~~~~~~~~~~ var1.c:7:9: note: ‘b’ was declared here 7 | int b; /* Variável declarada, mas não inicializada! */ | ^ cc1: all warnings being treated as errors
Atributos das variáveis
Toda variável tem como atributos…
- Um nome (identificador);
- Um valor associado;
- O endereço do valor associado.
O nome da variável expressa o seu valor:
int a = 21;
int b = a; // O valor de 'b' é o valor de 'a' (21).
int c = a + b; // O valor de 'c' é 21+21 (42).
Para que uma variável expresse o endereço do valor associado, nós utilizamos
o operador unário &
antes de seu nome:
int a = 123;
printf("Valor de a : %d", a);
printf("Endereço de a: %p", &a); // Imprime o endereço do dado em 'a'.
O tamanho do tipo da variável é expresso com o operador sizeof(VAR)
:
int a = 10;
int b = sizeof(a); // O valor de 'b' será 4 (bytes).
O tipo do valor expresso por
sizeof
ésize_t
, um apelido paraunsigned long
.
Escopo de variáveis
- Toda variável declarada numa função só é visível na própria função (escopo local).
- Toda variável declarada fora de funções é visível em todo o programa (escopo global).
Exemplo (var3.c
):
#include <stdio.h>
int c = 17; // Variável global.
// As variáveis 'num' e 'b' são locais à função 'soma10'.
int soma10(int num) {
int b = 10;
return b + num;
}
int main(void) {
int a = 25; // A variável 'a' é local à função 'main'.
// Isso causará um erro na compilação!
printf("a = %d\nb = %d\nc = %d\nnum = %d\n", a, b, c, num);
return 0;
}
Ponteiros
Antes de qualquer coisa, os ponteiros são simplesmente variáveis, embora possuam algumas particularidades:
- São declarados com o operador de derreferência (ou indireção)
*NOME
. - Recebem endereços como valores.
- Seus tipos são suas unidades aritméticas.
- Seus nomes expressam os endereços associados.
- Quando derreferenciados (
*NOME
), expressam os valores nos endereços.
Declaração do ponteiro
int a = 25;
int *pa = &a; // O valor de 'pa' será o endereço de 'a'.
int b = *pa; // O valor de 'b' será o valor no endereço em 'pa'.
Perguntas da aula
A cada execução do programa, os endereços das variáveis mudam?
Sim, porque o espaço de endereços é designado pelo sistema operacional assim que o processo para executar o programa é criado.
O ponto da declaração de uma variável global faz diferença?
Sim, toda variável tem que ser declarada antes do ponto no código em que é utilizada.