← Aulas

Arrays Bidimensionais

Matrizes em Linguagem C — declaração, inicialização, loops aninhados e aplicações em sistemas embarcados.

Disciplina:Introdução à Programação em C (EET126) Público-alvo:Licenciatura em Eng. Electrónica e Telecomunicações Carga Horária:2 horas (1h T + 1h P) Docente:Isac Osvaldo de Venâncio Daniel

Objectivos da Aula

02

Ao final desta aula, o estudante deverá ser capaz de:

  • Compreender o conceito de array bidimensional (matriz) e sua representação em memória
  • Declarar, inicializar e acessar elementos de matrizes em C
  • Utilizar loops aninhados para percorrer e manipular matrizes
  • Aplicar matrizes em sistemas embarcados: teclados, displays de LEDs, imagens e buffers
  • Avaliar o consumo de memória de matrizes em microcontroladores

O que é uma Matriz?

03

Estrutura de dados que organiza elementos do mesmo tipo em linhas e colunas. Podemos imaginá-la como uma tabela:

int mat[3][4];  // 3 linhas e 4 colunas

        Col0   Col1   Col2   Col3
Lin0  [0][0] [0][1] [0][2] [0][3]
Lin1  [1][0] [1][1] [1][2] [1][3]
Lin2  [2][0] [2][1] [2][2] [2][3]
💡
Cada elemento é acessado por dois índices: mat[linha][coluna]. Os índices começam sempre em 0.

Por que usar Matrizes?

04

📊 Dados tabulares

Notas de alunos, coordenadas, etc.

🖼️ Imagens

Matriz de pixels (tons de cinza ou RGB).

⌨️ Teclados

Teclados matriciais — linhas × colunas.

💡 Displays de LEDs

Matrizes 8×8 ou maiores, com multiplexação.

📡 Buffers

Amostras de múltiplos sensores ao longo do tempo.

🧮 Álgebra linear

Multiplicação, transposta, sistemas lineares.

Declaração de Matrizes

05

Sintaxe: <tipo> nomeMatriz[linhas][colunas];

int mat[3][4];          // 3 linhas, 4 colunas (12 inteiros)
float temperaturas[2][5];  // 2 linhas, 5 colunas (10 floats)
char tabuleiro[8][8];      // 8×8 caracteres

Com #define

#define LINHAS 3
#define COLUNAS 4
int mat[LINHAS][COLUNAS];

Inicialização — Lista Contínua

06
int mat[2][3] = {1, 2, 3, 4, 5, 6};

// Equivale a:
// mat[0][0]=1, mat[0][1]=2, mat[0][2]=3
// mat[1][0]=4, mat[1][1]=5, mat[1][2]=6

Por linhas (mais legível)

int mat[2][3] = {
    {1, 2, 3},
    {4, 5, 6}
};
✅
A forma por linhas é preferível — é mais legível e menos sujeita a erros.

Inicialização Parcial e com Zero

07

Parcial

int mat[3][3] = {
    {1, 2},        // linha 0: 1, 2, 0
    {4, 5, 6},     // linha 1: 4, 5, 6
    {7}           // linha 2: 7, 0, 0
};

Com zero (todos)

int mat[3][3] = {0};  // Todos os elementos valem 0

Primeira dimensão omitida

int mat[][3] = {
    {1, 2, 3},
    {4, 5, 6}
};  // Compilador conta: 2 linhas

Acesso aos Elementos e Loops Aninhados

08
int mat[2][3] = {{1,2,3},{4,5,6}};

int x = mat[1][2];  // x = 6
mat[0][1] = 20;    // Altera linha 0, coluna 1

Percorrer com loops aninhados

#define LINHAS 2
#define COLUNAS 3

int mat[LINHAS][COLUNAS] = {{1,2,3},{4,5,6}};
int i, j;

for (i = 0; i < LINHAS; i++) {
    for (j = 0; j < COLUNAS; j++) {
        printf("mat[%d][%d] = %d\n", i, j, mat[i][j]);
    }
}
🚫
Acessar fora dos limites (ex.: mat[2][3] numa matriz 2×3) causa comportamento indefinido — pode corromper memória.

Armazenamento na Memória (Row-Major)

09

Em C, matrizes são armazenadas em ordem row-major (linha por linha): primeiro a linha 0, depois a linha 1, etc.

int mat[2][3];  // 6 inteiros contíguos

Endereço base → [0][0] [0][1] [0][2] [1][0] [1][1] [1][2]
🧮
Endereço de mat[i][j]:
base + (i * num_colunas + j) * sizeof(tipo)

Consumo de Memória — Cuidados

10

Matrizes grandes consomem muita RAM. Em microcontroladores com poucos KB, isto é crítico.

Exemplo de consumo

  • int mat[10][10] → 100 inteiros → 200–400 bytes
  • float mat[10][10] → 100 floats → 400 bytes

⚠️ ATmega328P (Arduino UNO)

2 KB de SRAM. Uma única matriz float[10][10] ocupa 10% da RAM total.

⚠️
Usa const para matrizes que não mudam — vão para a memória de programa. Prefere tipos menores (char, int16) quando possível.

Preencher e Imprimir uma Matriz

11
#include <stdio.h>
#define LINHAS 3
#define COLUNAS 4

int main(void) {
    int mat[LINHAS][COLUNAS];
    int i, j;

    // Preencher
    for (i = 0; i < LINHAS; i++) {
        for (j = 0; j < COLUNAS; j++) {
            mat[i][j] = i * COLUNAS + j;
        }
    }

    // Imprimir como tabela
    for (i = 0; i < LINHAS; i++) {
        for (j = 0; j < COLUNAS; j++) {
            printf("%3d ", mat[i][j]);
        }
        printf("\n");
    }
    return 0;
}

Soma de Duas Matrizes

12
#define N 3
int A[N][N], B[N][N], C[N][N];
int i, j;

for (i = 0; i < N; i++) {
    for (j = 0; j < N; j++) {
        C[i][j] = A[i][j] + B[i][j];
    }
}
✅
A soma só é possível quando as matrizes têm a mesma dimensão. Cada elemento é somado posição a posição.

Matriz Transposta

13
#define L 2
#define C 3

int mat[L][C] = {{1,2,3},{4,5,6}};
int transposta[C][L];
int i, j;

for (i = 0; i < L; i++) {
    for (j = 0; j < C; j++) {
        transposta[j][i] = mat[i][j];
    }
}
🔁
A transposta troca linhas por colunas: T[j][i] = M[i][j].

Multiplicação de Matrizes

14

Dadas A (m × n) e B (n × r), o produto C (m × r) é calculado com três loops aninhados:

#define M 2
#define N 3
#define R 2

int A[M][N] = {{1,2,3},{4,5,6}};
int B[N][R] = {{7,8},{9,10},{11,12}};
int C[M][R];
int i, j, k;

for (i = 0; i < M; i++) {
    for (j = 0; j < R; j++) {
        C[i][j] = 0;
        for (k = 0; k < N; k++) {
            C[i][j] += A[i][k] * B[k][j];
        }
    }
}
⚠️
Condição de compatibilidade: nº colunas de A = nº linhas de B.

Teclado Matricial

15

Teclados matriciais organizam teclas em linhas e colunas. O microcontrolador faz uma varredura: activa uma linha e lê as colunas.

#define LINHAS 2
#define COLUNAS 5

char teclas[LINHAS][COLUNAS] = {
    {'1','2','3','4','5'},
    {'A','B','C','D','E'}
};

char lerTeclado(void) {
    int i, j;
    for (i = 0; i < LINHAS; i++) {
        // Ativa linha i, desativa as demais
        for (j = 0; j < COLUNAS; j++) {
            if (digitalRead(coluna[j]) == HIGH) {
                return teclas[i][j];
            }
        }
    }
    return 0;  // Nenhuma tecla
}

Matriz de LEDs — Padrões

16

Uma matriz de LEDs (ex.: 8×8) é controlada por linhas e colunas. Para exibir um padrão, guarda-se uma matriz de bits.

const char imagem[8][8] = {
    {0,0,0,1,1,0,0,0},
    {0,0,1,1,1,1,0,0},
    {0,1,1,0,0,1,1,0},
    {0,1,1,0,0,1,1,0},
    {0,0,1,1,1,1,0,0},
    {0,0,0,1,1,0,0,0},
    {0,0,0,0,0,0,0,0},
    {0,0,0,0,0,0,0,0}
};

Processamento de Imagens

17

Imagens em tons de cinza podem ser representadas por uma matriz de pixels. Filtros como média, bordas, etc., percorrem a matriz com loops aninhados.

#define LARGURA 320
#define ALTURA  240

unsigned char imagem[ALTURA][LARGURA];

// Exemplo: filtro de média 3x3
unsigned char media3x3(int y, int x) {
    int soma = 0;
    int i, j;
    for (i = -1; i <= 1; i++)
        for (j = -1; j <= 1; j++)
            soma += imagem[y + i][x + j];
    return soma / 9;
}

Buffer de Dados Bidimensionais

18

Armazena leituras de múltiplos sensores ao longo do tempo.

#define SENSORES 4
#define AMOSTRAS 100

int dados[SENSORES][AMOSTRAS];

// Exemplo: ler 4 sensores, 100 vezes
int s, a;
for (a = 0; a < AMOSTRAS; a++) {
    for (s = 0; s < SENSORES; s++) {
        dados[s][a] = adRead(s);
    }
    timerDelay(100);
}
📊
Permite calcular, por exemplo, a média por sensor ou detectar padrões ao longo do tempo.

Cuidados com Memória em Embarcados

19

✅ Prefere tipos menores

Usa char ou int16_t quando possível.

✅ Evita matrizes grandes locais

Variáveis locais vão para a pilha — que é pequena.

✅ Usa const

Matrizes constantes vão para memória de programa.

🚫 Evita float

Matrizes de float são especialmente custosas em RAM.

Exercícios Propostos

20

1 · Criação e Impressão

Matriz 3×3 preenchida com 1 a 9, impressa como tabela.

2 · Soma

Lê duas matrizes 3×3 e exibe a soma.

3 · Transposta

Matriz 4×4 e exibe a sua transposta.

4 · Multiplicação

Multiplica uma matriz 2×3 por uma 3×2.

5 · Média

Matriz 5×5: calcula a média e conta quantos elementos são maiores que ela.

6 · Teclado

Adapta a varredura para teclado 4×4 (linhas bits 0–3, colunas bits 4–7 da Porta B).

7 · Matriz LEDs

Cria um padrão de coração numa matriz 8×8.

8 · Buffer

Armazena 10 leituras de 3 sensores (matriz 3×10). Calcula média por sensor e exibe no LCD.

Resumo e Considerações Finais

21

📌 Conceitos-Chave

  • Matrizes são arrays de arrays
  • Indexação: mat[i][j]
  • Loops aninhados essenciais
  • Armazenamento em row-major

🔧 Aplicações

  • Teclados matriciais
  • Displays de LEDs
  • Processamento de imagens
  • Buffers bidimensionais

⚠️ Cuidados

  • Consumo de memória
  • Matrizes grandes podem esgotar a RAM
  • Usar const sempre que possível

🚀 Próximos Passos

  • Estruturas heterogéneas (struct)
  • Ponteiros
  • Optimização de memória

Bibliografia

22

📚 Principal

ASCENCIO, Ana F. G.; VENERUCH, Edilene A.
Fundamentos da Programação de Computadores. 3. ed. Pearson, 2014.

📚 Complementar

ALMEIDA, Rodrigo M. A.; MORAES, Carlos H. V.; SERAPHIM, Thatyana F. P.
Programação de Sistemas Embarcados. Elsevier, 2016. (Cap. 5 — Estruturas Compostas)

📚 Material Didático

Material do ISPSongo — Plano Analítico de Introdução à Programação em C.

Fim da Aula

Bons estudos e boa programação em C.

Próxima aula:Funções em Linguagem C Prática:Resolver exercícios 1 a 8
← Voltar à lista de aulas