Linguagem C: Vetores e Matrizes

De Aulas

Links relacionados: Programação em C

Ponteiros e Arrays

Figura 1 – Exemplo de posicionamento de um array na memória

Ponteiros são muito utilizados para a navegação de arrays, principalmente de arrays alocados de maneira dinâmica. A idéia geral é alocar o array usando ou o método estático ou o dinâmico e então criar uma variável do tipo ponteiro que apontará para a primeira posição do ponteiro. Utilizando aritmética de ponteiros (incremento, decremento, saltos) é possível percorrer o array sem ter que se preocupar com quantos bytes devem ser acessados, pois a tipagem do ponteiro cuidará deste detalhe.

É importante ressaltar que a utilização de ponteiros para indexação de arrays apresenta um risco intrínseco. Como C não é uma linguagem fortemente tipada, arrays não possuem um marcador de fim de alocação de memória tal como acontece em PASCAL. Ponteiros permitirão que a memória continue sendo acessada sequencialmente mesmo após o final da área previamente alocada para o array tenha sido toda percorrida.

Aritmética de Ponteiros

Uma das grandes vantagens decorrentes da utilização de ponteiros é a possibilidade de indexar posições de memória de maneira fácil e intuitiva. Tal endereçamento é alcançado a partir de operações aritméticas simples que tem como objetos variáveis do tipo ponteiro.

Operandos unários:

  • ++ incremento unitário;
  • -- decremento unitário.

Suponha que p é um ponteiro do tipo inteiro e suponha que o tipo inteiro na arquitetura de destino do exemplo sejam representados por 2 bytes cada. Considere o seguinte trecho de código:

1int vet[10]; 
2int *iptr; 
3iptr = vet; 
4iptr++;

Exemplo 4 – navegação de arrays usando ponteiros

Assumindo que o array “vet” seja alocado pelo “loader” do sistema operacional iniciando na posição 00H, iptr erá apontar para a posição 00H inicialmente. Ao se executar a operação iptr++, o endereço apontado por iptr será incrementado em uma unidade, o que corresponderá, dado o fato de que inteiros são representados por dois bytes, ao endereço 02H. (veja figura1 para exemplo)

Exemplo Estático

 1#include <stdio.h>
 2
 3#define SIZE    3
 4
 5void main() {
 6    int i, valor[SIZE];
 7    printf("Entre com %d valores inteiros...\n", SIZE);
 8    for (i = 0; i < SIZE; i++) {
 9        printf("Valor %d: ", i);
10        scanf("%d", &valor[i]);
11    }
12    printf("Os valores entrados foram: ");
13    for (i = 0; i < SIZE; i++) {
14        printf("%d ", valor[i]);
15    }
16    printf("\n");
17}

Exemplo vetor de duas dimensões

 1#include <stdio.h>
 2
 3int jogo[3][3];
 4
 5void mostrar() {
 6    int linha, coluna;
 7    for (linha = 0; linha < 3; linha++) {
 8        for (coluna = 0; coluna < 3; coluna++) {
 9            printf("%5d ", jogo[linha][coluna]);
10        }
11        printf("\n");
12    }
13}
14
15void ler() {
16    printf("Entre com a linha, a coluna e o valor: ");
17    int l, c, v;
18    scanf("%d %d %d", &l, &c, &v);
19    jogo[l][c] = v;
20}
21
22int main() {
23    for(;;) {
24        mostrar();
25        ler();
26    }
27}

Exemplo Dinâmico

 1#include <stdio.h>
 2#include <stdlib.h>
 3
 4#define SIZE    10
 5
 6int main() {
 7    int *iptr = (int*) malloc(SIZE * sizeof(int));
 8    int i;
 9    for (i = 0; i < SIZE; i++) {
10        iptr[i] = i * 10;
11    }
12    for (i = 0; i < SIZE; i++) {
13        printf("Elemento %d = %d\n", i, iptr[i]);
14    }
15    return 0;
16}

Alocação de vetores de Strings

 1#include <stdio.h>
 2#include <stdlib.h>
 3
 4#define SIZE	2
 5
 6int main() {
 7	int i;
 8	// Vetor estatico de strings estaticas
 9	char vet1[SIZE][255] =  { "Estatico-0", "Estatico-1" };
10	for (i = 0; i < SIZE; i++) {
11		printf("%s\n", vet1[i]);
12	}
13
14	// Vetor dinamico de strings dinamicas
15	char **vet;
16	vet = (char**) malloc (SIZE * sizeof(char*));
17	for (i = 0; i < SIZE; i++) {
18		vet[i] = malloc (255 * sizeof(char));
19		sprintf(vet[i], "Dinamico-%d", i);
20	}
21	for (i = 0; i < SIZE; i++) {
22		printf("%s\n", vet[i]);
23	}
24}

Exercícios

1. Qual será a saída do programa supondo que i ocupa o endereço 4094H na memória?

1int main( void ) { 
2  int i=5, *p; 
3  p=&i; 
4  printf(%d %d %d %d %d\n, p, *p+2, **&p, 3**p, **&p+4); 
5}

2. Assumindo que Pulo[] é um array do tipo int, quais das seguintes expressões referenciam o valor do terceiro elemento do array?

a) *(pulo+2)

b) *(pulo+4)

c) pulo+4

d) pulo+2

3. Suponha a declaração:

1int mat[4], *p, x;

Quais das expressões abaixo são válidas? Justifique:

a) p = mat+1;

b) p = mat++;

c) p = ++mat;

d) x = (*mat)++;


4. Explique a diferença entre os comandos abaixo: (assuma que p é um ponteiro do tipo int)

a) p++;

b) (*p)++;

c) *(p++);

5. Faça programas em C para resolver os seguintes problemas:

a) Somar a diagonal principal da matriz.

b) Mostrar o maior valor de cada linha

c) Criar a matriz transposta

d) Verificar se uma matriz é simétrica

e) Considerando uma matriz de notas com 10 linhas (uma para cada aluno) e 3 colunas (uma para cada prova), imprimir a tabela com a média de cada aluno, a média de cada prova e a média geral da turma.