A compreensão de como a linguagem C gerencia arrays e strings na memória é fundamental para o desenvolvimento de software eficiente. Este artigo explora a organização de dados em memória, técnicas de manipulação de strings e algoritmos clássicos aplicados a estruturas unidimensionais e multidimensionais.
1. Organização de Arrays na Memória
Arrays em C são armazenados em blocos contíguos de memória. Em um array unidimensional, os elementos seguem uma sequência linear. Já em arrays multidimensionais, o C utiliza a ordem row-major (armazenamento por linhas).
#include <stdio.h>
#define TAMANHO 4
void analisar_vetor_int() {
int numeros[TAMANHO] = {10, 20, 30, 40};
printf("Bytes ocupados pelo array: %zu\n", sizeof(numeros));
for (int i = 0; i < TAMANHO; ++i) {
printf("Endereco: %p | Valor: %d\n", (void*)&numeros[i], numeros[i]);
}
printf("Endereco base (nome do array): %p\n", (void*)numeros);
}
void analisar_vetor_char() {
char letras[TAMANHO] = {'A', 'B', 'C', 'D'};
printf("Bytes ocupados pelo array: %zu\n", sizeof(letras));
for (int i = 0; i < TAMANHO; ++i) {
printf("Endereco: %p | Valor: %c\n", (void*)&letras[i], letras[i]);
}
}
int main() {
analisar_vetor_int();
analisar_vetor_char();
return 0;
}
Ao observar os endereços de memória, nota-se que para int (geralmente 4 bytes), os endereços saltam de 4 em 4. Para char (1 byte), a sequência é unitária. O nome do array atua como um ponteiro para o primeiro elemento.
2. Arrays Bidimensionais e Aritmética de Endereços
Em matrizes, a memória continua sendo linear. O endereço de matriz[1][0] segue imediatamente o último elemento da primeira linha matriz[0][M-1].
#include <stdio.h>
#define LINHAS 2
#define COLUNAS 3
void explorar_matriz() {
int grade[LINHAS][COLUNAS] = {{1, 2, 3}, {4, 5, 6}};
for (int i = 0; i < LINHAS; i++) {
for (int j = 0; j < COLUNAS; j++) {
printf("[%d][%d] em %p\n", i, j, (void*)&grade[i][j]);
}
}
printf("grade: %p\ngrade[0]: %p\ngrade[1]: %p\n", (void*)grade, (void*)grade[0], (void*)grade[1]);
}
3. Permutação de Strings
Para trocar o conteúdo de duas strings, é necessário utilizar uma área de armazenamento temporária, já que strings em C são arrays de caracteres e não podem ser atribuídas diretamente com o operador =.
#include <stdio.h>
#include <string.h>
void trocar_strings(char str_a[], char str_b[]) {
char buffer[100];
strcpy(buffer, str_a);
strcpy(str_a, str_b);
strcpy(str_b, buffer);
}
int main() {
char s1[100] = "Texto Alpha";
char s2[100] = "Texto Beta";
trocar_strings(s1, s2);
printf("S1: %s\nS2: %s\n", s1, s2);
return 0;
}
4. Processamento de Texto: Contagem e Busca
Abaixo, um exemplo de como processar uma string para contar palavras e identificar a maior delas com base em delimitadores de espaço.
#include <stdio.h>
#include <string.h>
void identificar_maior_palavra(char texto[]) {
int i = 0, atual_len = 0, max_len = 0, pos_final = 0;
while (1) {
if (texto[i] == ' ' || texto[i] == '\0') {
if (atual_len > max_len) {
max_len = atual_len;
pos_final = i;
}
atual_len = 0;
if (texto[i] == '\0') break;
} else {
atual_len++;
}
i++;
}
printf("Maior comprimento: %d. Palavra: ", max_len);
for (int j = pos_final - max_len; j < pos_final; j++) {
putchar(texto[j]);
}
putchar('\n');
}
5. Conversão de Base Numérica
Utilizando arrays para armazenar restos de divisões sucessivas, podemos converter números decimais para outras bases (binária, octal ou hexadecimal).
#include <stdio.h>
void converter_base(int decimal, int base) {
char simbolos[] = "0123456789ABCDEF";
char resultado[64];
int indice = 0;
if (decimal == 0) {
printf("0\n");
return;
}
while (decimal > 0) {
resultado[indice++] = simbolos[decimal % base];
decimal /= base;
}
for (int i = indice - 1; i >= 0; i--) {
putchar(resultado[i]);
}
putchar('\n');
}
6. Ordenação e Estatística em Vetores
O algoritmo Bubble Sort é uma técnica comum para ordenar elementos. Combinado com funções de entrada e saída, permite gerenciar cnojuntos de dados numéricos.
#include <stdio.h>
void ordenar_decrescente(int dados[], int n) {
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (dados[j] < dados[j + 1]) {
int temp = dados[j];
dados[j] = dados[j + 1];
dados[j + 1] = temp;
}
}
}
}
float calcular_media(int dados[], int n) {
float soma = 0;
for (int i = 0; i < n; i++) soma += dados[i];
return soma / n;
}
7. Rotação de Matrizes
Operações em matrizes podem incluir transformações geométricas ou deslocamentos. O exemplo a seguir demonstra o deslocamento cíclico das colunas de uma matriz para a direita.
#include <stdio.h>
#define N 4
void rotacionar_colunas(int mat[N][N]) {
for (int i = 0; i < N; i++) {
int ultimo = mat[i][N - 1];
for (int j = N - 1; j > 0; j--) {
mat[i][j] = mat[i][j - 1];
}
mat[i][0] = ultimo;
}
}
void exibir_matriz(int mat[N][N]) {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
printf("%3d ", mat[i][j]);
}
printf("\n");
}
}