Tabelas de dados na memória — linhas, colunas e row-major order
Um array unidimensional armazena uma sequência de valores — como uma fila. Uma matriz é um array de duas dimensões: linhas e colunas, como uma tabela ou planilha.
tipo nome[linhas][colunas] e armazenada na memória de forma contígua em row-major order (linha por linha).
Uma matriz int notas[3][4] representa 3 alunos com 4 notas cada:
| Coluna 0 (Nota 1) | Coluna 1 (Nota 2) | Coluna 2 (Nota 3) | Coluna 3 (Nota 4) | |
|---|---|---|---|---|
| Linha 0 (Aluno A) | notas[0][0] = 7 |
notas[0][1] = 8 |
notas[0][2] = 6 |
notas[0][3] = 9 |
| Linha 1 (Aluno B) | notas[1][0] = 5 |
notas[1][1] = 7 |
notas[1][2] = 8 |
notas[1][3] = 6 |
| Linha 2 (Aluno C) | notas[2][0] = 9 |
notas[2][1] = 10 |
notas[2][2] = 8 |
notas[2][3] = 7 |
[7][8][6][9][5][7][8][6][9][10][8][7].
int matriz[2][2]; // declara sem inicializar (contém lixo de memória)
matriz[0][0] = 1;
matriz[0][1] = 2;
matriz[1][0] = 3;
matriz[1][1] = 4;
int matriz[2][3] = {
{1, 2, 3}, // linha 0
{4, 5, 6} // linha 1
};
int matriz[2][3] = {1, 2, 3, 4, 5, 6}; // C preenche linha por linha
int matriz[3][3] = { {1}, {4, 5} };
// Resultado:
// 1 0 0
// 4 5 0
// 0 0 0
char dias[7][12] = {
"Segunda", "Terça", "Quarta",
"Quinta", "Sexta", "Sábado", "Domingo"
};
printf("%s\n", dias[0]); // imprime: Segunda
int m[][3] = ...), mas nunca as colunas.
O padrão universal para percorrer uma matriz é usar dois loops for aninhados: o externo para as linhas e o interno para as colunas.
#include <stdio.h>
int main() {
int matriz[2][2];
int i, j;
// Leitura: preenche com scanf
for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
printf("Digite matriz[%d][%d]: ", i, j);
scanf("%d", &matriz[i][j]);
}
}
// Impressão
printf("\nMatriz:\n");
for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
printf("%4d", matriz[i][j]); // %4d: largura mínima 4 para alinhar
}
printf("\n"); // quebra de linha ao final de cada linha
}
return 0;
}
Para trocar duas linhas de uma matriz, usamos variáveis temporárias — o mesmo padrão do swap de variáveis, mas dentro de um loop de colunas:
#include <stdio.h>
int main() {
int m[2][2], temp, i;
// Leitura da matriz
printf("Digite [0][0]: "); scanf("%d", &m[0][0]);
printf("Digite [0][1]: "); scanf("%d", &m[0][1]);
printf("Digite [1][0]: "); scanf("%d", &m[1][0]);
printf("Digite [1][1]: "); scanf("%d", &m[1][1]);
// Troca das linhas 0 e 1
for (i = 0; i < 2; i++) {
temp = m[0][i]; // guarda elemento da linha 0
m[0][i] = m[1][i]; // sobrescreve com linha 1
m[1][i] = temp; // restaura na linha 1
}
// Impressão
printf("\nMatriz após troca:\n");
printf("%d %d\n", m[0][0], m[0][1]);
printf("%d %d\n", m[1][0], m[1][1]);
return 0;
}
| Antes | Depois |
|---|---|
| 1 2 / 3 4 | 3 4 / 1 2 |
#include <stdio.h>
#define L 2
#define C 3
int main() {
int a[L][C] = {{1,2,3},{4,5,6}};
int b[L][C] = {{7,8,9},{1,2,3}};
int soma[L][C];
int i, j;
for (i = 0; i < L; i++)
for (j = 0; j < C; j++)
soma[i][j] = a[i][j] + b[i][j];
printf("Resultado da soma:\n");
for (i = 0; i < L; i++) {
for (j = 0; j < C; j++)
printf("%4d", soma[i][j]);
printf("\n");
}
return 0;
}
A transposta troca linhas por colunas: o elemento [i][j] vai para [j][i].
#include <stdio.h>
#define N 3
int main() {
int m[N][N] = {{1,2,3},{4,5,6},{7,8,9}};
int t[N][N]; // matriz transposta
int i, j;
for (i = 0; i < N; i++)
for (j = 0; j < N; j++)
t[j][i] = m[i][j]; // troca índices
printf("Transposta:\n");
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++)
printf("%3d", t[i][j]);
printf("\n");
}
return 0;
}
Matrizes, assim como arrays 1D, são passadas automaticamente por ponteiro — a função recebe o endereço do primeiro elemento e pode modificar os dados originais.
#include <stdio.h> #define COLS 3 // ✅ Correto: número de colunas especificado void imprimirMatriz(int m[][COLS], int linhas) { int i, j; for (i = 0; i < linhas; i++) { for (j = 0; j < COLS; j++) printf("%4d", m[i][j]); printf("\n"); } } // Equivalente com ponteiro explícito (C99+) void dobrarElementos(int m[][COLS], int linhas) { int i, j; for (i = 0; i < linhas; i++) for (j = 0; j < COLS; j++) m[i][j] *= 2; // modifica o original (passagem por ponteiro) } int main() { int tabela[2][COLS] = {{1,2,3},{4,5,6}}; printf("Original:\n"); imprimirMatriz(tabela, 2); dobrarElementos(tabela, 2); printf("Após dobrar:\n"); imprimirMatriz(tabela, 2); return 0; }
const int m[][COLS] se quiser garantir que a função não modifique os dados.
| Aspecto | C | Java |
|---|---|---|
| Declaração | int m[3][4]; |
int[][] m = new int[3][4]; |
| Armazenamento | Bloco contíguo (row-major) | Array de arrays (referências) |
| Linhas de tamanhos diferentes (jagged) | ❌ Não suportado nativamente | ✅ Cada linha pode ter tamanho diferente |
| Verificação de limites | ❌ Nenhuma — comportamento indefinido | ✅ Lança ArrayIndexOutOfBoundsException |
| Tamanho em tempo de execução | sizeof(m) / sizeof(m[0]) (apenas local) |
m.length e m[0].length |
| Passagem para função | Por ponteiro (obriga informar colunas) | Por referência automática |
int a[2][2] = {{1,2},{3,4}};
int b[2][2] = {{5,6},{7,8}};
int s[2][2];
for (int i=0; i<2; i++)
for (int j=0; j<2; j++)
s[i][j] = a[i][j]+b[i][j];
int[][] a = {{1,2},{3,4}};
int[][] b = {{5,6},{7,8}};
int[][] s = new int[2][2];
for (int i=0; i<2; i++)
for (int j=0; j<2; j++)
s[i][j] = a[i][j]+b[i][j];