cblc/aulas/04-variaveis/README.org
2025-03-20 15:05:11 -03:00

4.6 KiB
Raw Permalink Blame History

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 para unsigned 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.