sizeof e pointer decay, arrays multidimensionais, exemplo completo e C vs Java
sizeofEm Java, todo array tem a propriedade .length. Em C, arrays não carregam seu tamanho consigo. Você precisa rastrear o tamanho manualmente — ou usar um truque com sizeof.
sizeof(array) retorna o tamanho total em bytes ocupado pelo array inteiro. sizeof(array[0]) retorna o tamanho em bytes de um único elemento. Dividindo um pelo outro, obtemos o número de elementos.
#include <stdio.h>
int main() {
int v[] = {10, 20, 30, 40, 50};
int bytes_total = sizeof(v); // 5 * 4 = 20 bytes
int bytes_elem = sizeof(v[0]); // 4 bytes (um int)
int num_elementos = sizeof(v) / sizeof(v[0]);// 20 / 4 = 5
printf("Tamanho total: %d bytes\n", bytes_total);
printf("Tamanho de um elemento: %d bytes\n", bytes_elem);
printf("Número de elementos: %d\n", num_elementos);
for (int i = 0; i < num_elementos; i++)
printf("%d ", v[i]);
printf("\n");
return 0;
}
sizeof(v)/sizeof(v[0]) funciona somente no mesmo escopo em que o array foi declarado. Quando você passa um array para uma função, ele se transforma em ponteiro — e o sizeof passa a retornar o tamanho do ponteiro (4 ou 8 bytes), não do array inteiro!
#include <stdio.h>
void imprimirArray(int arr[], int n) {
// sizeof(arr) aqui retorna sizeof(int*) = 8 bytes (ponteiro!)
// NÃO use sizeof(arr)/sizeof(arr[0]) dentro de funções!
printf("sizeof dentro da função: %zu\n", sizeof(arr)); // imprime 8, não 20!
for (int i = 0; i < n; i++) // por isso passamos 'n' separadamente
printf("%d ", arr[i]);
printf("\n");
}
int main() {
int v[] = {10, 20, 30, 40, 50};
int n = sizeof(v) / sizeof(v[0]); // 5 — funciona aqui, onde v foi declarado
printf("sizeof em main: %zu\n", sizeof(v)); // imprime 20 (correto)
imprimirArray(v, n); // passa o tamanho explicitamente!
return 0;
}
Quando um array é passado para uma função, C não copia todos os elementos — isso seria lento e caro. Em vez disso, passa apenas o endereço do primeiro elemento: um ponteiro. Esse fenômeno chama-se pointer decay (decaimento de array para ponteiro). Com isso, o compilador perde a informação do tamanho original.
imprimirArray(v, n), C entrega à função apenas o endereço de v[0] — um número de 8 bytes que aponta para o início do array. A função recebe esse endereço, mas não sabe quantos elementos existem a partir daí. Por isso toda função em C que recebe um array precisa receber o tamanho como parâmetro separado.
| Contexto | C | Java |
|---|---|---|
| Obter tamanho do array | sizeof(v)/sizeof(v[0]) — só funciona localmente |
v.length — funciona em qualquer lugar |
| Dentro de uma função | Deve receber int n como parâmetro separado |
v.length continua disponível |
| O que é passado à função | Apenas o endereço do 1º elemento (ponteiro) | Referência ao objeto array (que carrega o length) |
int n). Você nunca consegue descobrir o tamanho de um array dentro da função que o recebeu. Essa é uma diferença fundamental em relação ao Java, onde array.length funciona em qualquer contexto.
C suporta arrays com mais de uma dimensão. O caso mais comum é o array bidimensional, útil para representar matrizes, tabelas e grades.
// Matriz 3x4: 3 linhas, 4 colunas int matriz[3][4]; // Inicialização com listas aninhadas int m[3][4] = { {1, 2, 3, 4}, // linha 0 {5, 6, 7, 8}, // linha 1 {9, 10, 11, 12} // linha 2 }; // Acesso: m[linha][coluna] printf("%d\n", m[1][2]); // 7 (linha 1, coluna 2)
#include <stdio.h>
int main() {
int m[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
for (int i = 0; i < 3; i++) { // percorre linhas
for (int j = 0; j < 4; j++) { // percorre colunas
printf("%4d", m[i][j]); // %4d: campo de 4 caracteres
}
printf("\n");
}
return 0;
}
Em C, matrizes são armazenadas na memória linha por linha (row-major order): todos os elementos da linha 0 vêm primeiro, depois os da linha 1, e assim por diante. Isso é importante para performance: percorrer coluna por coluna é muito mais lento do que percorrer linha por linha, pois prejudica o cache do processador.
| Posição na memória | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Elemento | m[0][0] | m[0][1] | m[0][2] | m[0][3] | m[1][0] | m[1][1] | m[1][2] | m[1][3] | m[2][0] | m[2][1] | m[2][2] | m[2][3] |
| Valor | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
Vamos escrever um programa que lê um vetor de inteiros e calcula mínimo, máximo, soma e média:
#include <stdio.h>
#define MAX 100
int main() {
int v[MAX], n;
/* lê o número de elementos */
do {
printf("Quantos elementos? (1 a %d): ", MAX);
scanf("%d", &n);
} while (n < 1 || n > MAX);
/* lê os elementos */
for (int i = 0; i < n; i++) {
printf("v[%d]: ", i);
scanf("%d", &v[i]);
}
/* calcula estatísticas */
int min = v[0], max = v[0];
long soma = 0;
for (int i = 0; i < n; i++) {
if (v[i] < min) min = v[i];
if (v[i] > max) max = v[i];
soma += v[i];
}
printf("\nMínimo: %d\n", min);
printf("Máximo: %d\n", max);
printf("Soma: %ld\n", soma);
printf("Média: %.2f\n", (double)soma / n); // cast para não truncar
return 0;
}
min e max com v[0] — não com 0 ou com INT_MAX. Isso garante que o algoritmo funcione mesmo que todos os elementos sejam negativos (min = 0 seria errado nesse caso) ou muito grandes (max = 0 poderia ser menor que todos os elementos).
| Aspecto | C | Java |
|---|---|---|
| Declaração | int v[5]; |
int[] v = new int[5]; |
| Inicialização padrão | ❌ Contém lixo de memória | ✅ Zeros automáticos (int), null (objetos) |
| Verificação de limites | ❌ Nenhuma — UB silencioso | ✅ ArrayIndexOutOfBoundsException |
| Tamanho do array | sizeof(v)/sizeof(v[0]) — só localmente |
v.length — em qualquer lugar |
| Passagem para função | Decai para ponteiro; tamanho se perde — deve ser passado separado | Passa referência ao objeto; .length continua acessível |
| Tamanho variável | VLA (C99) — mas não recomendado; preferir #define ou parâmetro |
new int[n] — dinâmico e natural |
| Cópia de array | memcpy(dest, src, n*sizeof(int)); — manual |
Arrays.copyOf(src, n); — automático |
| Ordenação | qsort(v, n, sizeof(int), comparador); |
Arrays.sort(v); |
| Array de strings | char nomes[10][50]; — matriz de char |
String[] nomes = new String[10]; |
| For-each | ❌ Não existe — use for (int i=0; i<n; i++) |
✅ for (int x : v) |
=!= não copia arrays:
int a[5] = {1,2,3,4,5};
int b[5];
b = a; // ERRO DE COMPILAÇÃO em C!
int a[5] = {1,2,3,4,5};
int b[5];
for (int i = 0; i < 5; i++)
b[i] = a[i]; // cópia manual
/* ou usando memcpy de <string.h>: */
memcpy(b, a, 5 * sizeof(int));
Questões sobre sizeof, pointer decay, matrizes e C vs Java.