Linguagem de programação I A Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação Versão: 220514_01.

Slides:



Advertisements
Apresentações semelhantes
Laboratório de programação III Linguagem C
Advertisements

Marco Antonio Montebello Júnior
Programação II Estruturas de Dados
Alocação Dinâmida de Memória
Algoritmos e Estrutura de Dados I
1 Tipos definidos O programador pode definir seus próprios tipos de dados tipos complexos usados da mesma forma que os simples declaram-se variáveis utilizando-se.
Linguagem C LPG-I – Variáveis Estruturadas – Vetores
LPG - I: Alocação Dinâmica de Memória - Ponteiros
LPG - I: Ponteiros e Vetores/Matrizes UDESC - SBS
LPG-I: Tipos Complexos - Estruturas
Estruturas de Dados II Prof.: Sergio Pacheco Prof.: Sergio Pacheco 1 1.
Universidade de Brasília
LINGUAGEM C Centro Federal de Educação Tecnológica da Paraíba Coordenação de Informática Professor: Lafayette B. Melo.
Linguagem C Strings.
Vetores, Matrizes e Funções
Ponteiros em Linguagem C
Slides Prof. Jean SIMÃO Revisão: Prof. João FABRO
Fundamentos de Programação 1
Ponteiros.
Escola Secundária c/ 3º CEB da Batalha
Escola Secundária c/ 3º CEB da Batalha
Listas Encadeadas.
Revisão da Linguagem C.
Apontadores ou Ponteiros
APRESENTAÇÃO: GIANCARLO DE GUSMÃO GONÇALVES CURSO DE C AULA 08: Tipos Estruturados.
Professor Reverton de Paula Faculdade Anhanguera de Indaiatuba
Alocação Dinâmica de Memória Professor Mário Dantas
Aula prática 9 Alocação Dinâmica Monitoria de Introdução à Programação
Aula prática 8 Ponteiros Monitoria de Introdução à Programação
Aula prática 8 Ponteiros Monitoria de Introdução à Programação.
Aula prática 6 Vetores e Matrizes
Aula prática 9 Alocação Dinâmica Monitoria de Introdução à Programação
PROGRAMAÇÃO ESTRUTURADA II
Linguagem de Programação II Parte IX
Definição de Tipos Estruturas e Ponteiros
CADEIA DE CARACTERES (Strings)
Estrutura de dados II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.
Linguagem de programação I A Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.
Alocação Dinâmica de Memória
UNIDADE 5 ESTRUTURAS DE DADOS HOMOGÊNEAS
Aula Prática 12 Operações com Arquivos Monitoria
Professor Mário Dantas
Prof. Ricardo Santos PONTEIROS
Linguagem C : Ponteiros
Linguagem de programação I A Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.
Estruturas de Dados Aula 2: Estruturas Estáticas 07/04/2014.
Educação Profissional Técnica de Nível Médio Curso Técnico de Informática
1 Alocação Dinâmica Quando se declara arrays o tamanho deve ser fixo e definido primeiramente –Alocação estática Pode-se alocar dinamicamente o espaço.
Algoritmos e Estruturas de Dados
Joaquim José Hangalo  Podemos entender a memória do computador como um conjunto de células que armazenam informações.  Cada célula.
Estruturas de Dados Aulas 3 e 4: Uso da memória e Vetores
Linguagem de programação I A Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação Versão: _01.
CES-10 INTRODUÇÃO À COMPUTAÇÃO
Algoritmos e Programação MC102 Prof. Paulo Miranda IC-UNICAMP Aula 15 Ponteiros.
Programação Computacional Aula 8: Entrada e Saída pelo Console Prof a. Madeleine Medrano
Programação de Computadores I – Ponteiros Profa. Mercedes Gonzales Márquez.
Leandro Almeida  As declarações abaixo alocam memória para diversas variáveis.  A alocação é estática, pois acontece antes que o programa.
Ponteiros em C Prof. Kariston Pereira
Linguaguem de Programação II
Estrutura de Dados Revisão Professor Luiz José Hoffmann Filho
 O que são arrays:  estruturas de dados homogêneas  coleção de elementos do mesmo tipo referenciada por um nome comum  um array pode ser imaginado.
Estruturas Homogêneas – Vetores e Matrizes
Ponteiros. Programação II Professora: Mai-Ly vanessa horário: ter 9h-11h; sex 11h-13h Aula 1.
Algoritmo e Estrutura de Dados I Aulas 15 – Linguagem C Alocação Dinâmica de Memória Márcia Marra
Linguagem de Programação
Programação em C Aula 9.
Arrays Outline 7.1 Introdução 7.2 Arrays 7.3 Declarando e Criando Arrays 7.4 Exemplos usando arrays 7.5 Ordenando arrays 7.6 Procurando em.
Aula Prática 6 Ponteiros Monitoria  Quando declaramos uma matriz:  tipo meuArray[tam];  O compilador aloca a matriz em uma região de memória.
Alocação Dinâmica Dilvan Moreira. Objetivos  Entender o que são e como usar:  Gerenciamento de Memória  Alocação Dinâmica em C.
FUNÇÕES Dilvan Moreira (baseado em material de Z. Liang)
Transcrição da apresentação:

Linguagem de programação I A Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação Versão: _01

Ponteiros

O C é altamente dependente dos ponteiros. Para ser um bom programador em C é fundamental que se tenha um bom domínio deles O Ministério da Saúde adverte: o uso descuidado de ponteiros pode levar a sérios bugs e a dores de cabeça terríveis :-).

Ponteiros em Linguagem C O Que é uma variável? É uma área da memória do computador onde é armazenado um valor…. Exemplo 1: int a = 1;  Atribui ao endereço 1000 o valor VariávelPosição a1000

Ponteiros em Linguagem C O Que É Um Ponteiro? Um ponteiro é uma variável que aponta para outra variável. Isto significa que um ponteiro mantém o endereço de memória de outra variável. Em outras palavras, o ponteiro não contém um valor no sentido tradicional, mas sim o endereço de outra variável. Um ponteiro "aponta para" esta outra variável mantendo uma cópia de seu endereço Convém dizer que a expressão “apontar para...” significa “armazenar o endereço de memória de...” Como um ponteiro contém um endereço, e não um valor, terá duas partes. O ponteiro contém um endereço e o endereço aponta para um valor. Há o ponteiro e o valor para o qual ele aponta. Este fato pode ser um tanto confuso, até você se familiarizar com ele. Superada a etapa da familiarização, ele se torna extremamente eficaz.

Ponteiros em Linguagem C Operadores relacionados a Ponteiros: *(asterisco): informa que uma variável irá armazenar o endereço de outra variável; ou: Informa ao computador que você deseja o conteúdo que está no endereço armazenado; - Pode ser lido como “o conteúdo no endereço” q = *m;  q recebe o valor armazenado no endereço m & (e comercial): retorna o endereço de uma variável; - Pode ser lido como “o endereço de” m = &count;  m recebe o endereço de count

Ponteiros em Linguagem C int main() { int i,j; int *p; p = &i; *p=5; j=i; printf(("%d %d %d\n", i, j, *p); return 0; } ==> 5 5 5

Operadores de ponteiros * (asterisco) indica que a variável é um ponteiro tipo_dado *nome_ponteiro; Ex: int x; int *pi; /* compilador sabe que pi é ponteiro */ /* pi é um ponteiro para inteiro */

Operadores de ponteiros o operador “&” quando aplicado sobre uma variável retorna o seu endereço Ex: int x = 10, *pi; pi = &x; printf(“&x: %p pi: %p”, &x, pi); => &x: 0x03062fd8 pi: 0x03062fd8

Operadores de ponteiros o operador “*” quando aplicado sobre um ponteiro retorna o dado apontado Ex: void main () { int *tmp_ptr; int x, y; x = 10; tmp_ptr = &x; y = *tmp_ptr; /* (*tmp_ptr) = 10 */ }

Outro exemplo ilustrado int i; int *p; p = &i; *p=5;

Relembrando... operador * Usado na declaração de um ponteiro int *x Usado para acessar o conteúdo de um endereço apontado *x = 10; // atribui o valor 10 ao local apontado pelo ponteiro ‘x’ printf(“%d”, *x); // imprime o valor armazenado no local apontado por ‘x’ operador & acessa o endereço de uma variável

Exemplo de uso int a = 1;  declara variavel inteiro com valor 1 int *pt_a;  declara um ponteiro para um inteiro pt_a = &a;  ponteiro recebe o endereco da variavel a printf(“%d”, *pt_a);  imprime o valor apontado pelo ponteiro

Ponteiros ponteiros são variáveis tipadas: (int *) ≠ (float *) ≠ (char *) As variaveis ponteiro devem sempre apontar para os tipos de dados corretos. Uma variavel ponteiro declarada como apontador de dados inteiros deve sempre apontar para dados deste tipo. Ex: main() { int *ip, x; float *fp, z; ip = &x; /* OK */ fp = &z; /* OK */ ip = &z; /* erro */ fp = &x; /* erro */ }

Ponteiros espaço ocupado pelas variáveis Ponteiro aponta para o tamanho segundo seu tipo 1 byte (int *) 1 byte (float *) (char *)

Exemplo de uso Exemplo: int a = 1; int *pt_a; pt_a = &a; VariávelPosição a1000 pt_a1001

Ponteiros em Linguagem C Onde usar isto??? Funções! Alocação Dinâmica Não sei o tamanho que o vetor precisa ter….! Não sei o tamanho que cada string precisa ter… Não sei o tamanho que a matriz precisa ter…

Utilizando Ponteiros void main() { int x = 10; int *pi; pi = &x; /* *pi == 10 */ (*pi)++; /* *pi == 11 */ printf(“%d”, x); } ==> 11 ao alterar *pi estamos alterando o conteúdo de x

Utilizando Ponteiros void main() { int x = 10; int *pi, *pj; pi = &x; /* *pi == 10 */ pj = pi; /* *pj == 10 */ (*pi)++; /* (*pi, *pj, x) == 11 */ (*pj)++; /* (*pi, *pj, x) == 12 */ printf(“%d”, x); /* ==> 12 */ printf(“%x”, &pj); /* Endereco de x ==> 0x0c220c */ }

Arrays e ponteiros Lembrando: arrays são agrupamentos de dados adjacentes na memória declaração: tipo nome_array[ ]; define um arranjo de elementos adjacentes na memória do tipo tipo_dado

Arrays e ponteiros’ Representação na memória: float m[10], *pf; pf = m; m pf Note que m é um ponteiro !!!!

Referenciando Arrays em float m[10] m é uma constante que endereça o primeiro elemento do array portanto, não é possível mudar o valor de m Ex: float m[10], n[10]; float *pf; m = n;/* erro: m é constante ! */ pf = m; /* ok */

Referenciando Elementos pode-se referenciar os elementos do array através do seu nome e colchetes: m[5] = 5.5; if (m[5] == 5.5) printf(“Exito”); else printf(“Falha”);

Referenciando Elementos Pode-se referenciar os elementos de um array através de ponteiros: float m[ ] = { 1.0, 3.0, 5.75, }; float *pf; pf = &m[2]; printf(“%f”, *pf);/* ==> 5.75 */

Referenciando Elementos Pode-se utilizar ponteiros e colchetes: float m[] = { 1.0, 3.0, 5.75, }; float *pf; pf = &m[2]; printf(“%f”, pf[0]);/* ==> 5.75 */ Note que o valor entre colchetes é o deslocamento a ser considerado a partir do endereço de referência pf[n] => indica enésimo elemento a partir de pf

Exemplo void main () { int arint[ ] = { 1,2,3,4,5,6,7 }; int size = 7;/* tamanho do array */ int i, *pi; for (pi=arint, i=0; i < size; i++, pi++) printf(“ %d “, *pi); } ==>

Exemplo - variação void main () { int arint[] = { 1,2,3,4,5,6,7 }; int size = 7;/* tamanho do array */ int i, *pi; for (pi=arint, i=0; i < size; i++) printf(“ %d “, *pi++); } ==>

Exemplo - variação void main () { int arint[] = { 1,2,3,4,5,6,7 }; int size = 7;/* tamanho do array */ int i, *pi; pi = arint; printf(“ %d “, *pi); pi += 2; printf(“ %d “, *pi); } ==>

Isso causa a maior confusão.... int main() { int vetor[] = {1, 3, 5, 7, 9}; int *p = vetor; printf("%d \n", *p ); /* imprime 1 (posicao 0)*/ printf("%d \n", *p++ ); /* imprime 1 e incrementa o p para proxima posicao (posicao 1) */ printf("%d \n", (*p)++ ); /* imprime 3 e incrementa valor que esta posicao 1 (onde p aponta) */ printf("%d \n", *p ); /* p estah apontando para posicao 1, imprime 4 */ p++; /* p agora aponta para a proxima posicao, isto eh posicao 2, valor 5 */ printf("%d - %p\n", *p, p); /* imprime posicao 2, valor 5 */ ==> Resumindo: p++  incrementa o ponteiro para próxima posição *p++  retorna o valor para onde p aponta e depois incrementa o p para próxima posição (*p)++  retorna o valor para onde p aponta e depois incrementa o valor que está ali armazenado (não muda a posição de p) Resumindo: p++  incrementa o ponteiro para próxima posição *p++  retorna o valor para onde p aponta e depois incrementa o p para próxima posição (*p)++  retorna o valor para onde p aponta e depois incrementa o valor que está ali armazenado (não muda a posição de p)

Aritmética de Ponteiros É possível fazer operações aritméticas e relacionais entre ponteiros e inteiros

Aritmética de Ponteiros Atribuição: Da mesma maneira que ocorre com uma variável comum, o conteúdo de um ponteiro pode ser passado para outro ponteiro do mesmo tipo. Observar que em C é possível atribuir qualquer endereço a uma variável ponteiro. Deste modo é possível atribuir o endereço de uma variável do tipo float a um ponteiro do tipo int. No entanto, o programa não irá funcionar da maneira correta..... int vetor [] = { 10, 20, 30, 40, 50 }; int *p1, *p2; int i = 100; p1 = & vetor [2]; p2 = &i; p2 = p1;...

Aritmética de Ponteiros Soma e subtração: Quando soma-se 1 a uma variável seu valor é incrementado em 1. No caso de ponteiros quando adiciona-se 1 o valor é incrementado de um valor que corresponde a quantidade de bytes do tipo para o qual aponta Assim, ao somar 1 a um ponteiro de int o seu valor será incrementado em 4 (devido a int = 4 bytes) Ao somar-se um inteiro n a um ponteiro, endereçamos n elementos a mais (n positivo) ou a menos (n negativo) pf[2] equivale a *(pf+2) *(pf + n) endereça n elementos a frente *(pf - n) endereça n elementos atrás pf++ endereça próximo elemento array pf--endereça elemento anterior array

Aritmética de Ponteiros Exemplos p = p + 3;  p aponte para o terceiro elemento após o atual *(p+1)=10;  armazena o valor 10 na posição seguinte A diferença entre ponteiros fornece quantos elementos do tipo do ponteiro existem entre os dois ponteiros int main (void) { float vetor [] = { 1.0, 2.0, 3.0, 4.0, 5.0 }; float *p1, *p2; p1 = & vetor [2]; /* endereco do terceiro elemento */ p2 = vetor; /* endereco do primeiro elemento */ printf(" Diferenca entre ponteiros %d\n", p1 -p2 ); return 0; } ==> 2

Operações Válidas Sobre Ponteiros É valido: somar ou subtrair um inteiro a um ponteiro (pi ± int) incrementar ou decrementar ponteiros (pi++, pi--) subtrair ponteiros (produz um inteiro) (pf - pi) comparar ponteiros ( >, >=, <, <=, == ) Não é válido: somar ponteiros(pi + pf) multiplicar ou dividir ponteiros (pi*pf, pi/pf) operar ponteiros com double ou float (pi ± 2.0)

Cuidados... C não controla os limites dos arrays, o programador deve fazê-lo Ex: encontrar o erro: void main () { int arint[] = { 1,2,3,4,5,6,7 }; int size = 7, i, *pi; for (pi=arint, i=0; i < size; i++, pi += 2) printf(“ %d “, *pi); }

Cuidados... void main () { int arint[] = { 1,2,3,4,5,6,7 }; int size = 10; int i; for (pi=arint, i=0; i < size; i++) printf(“ %d “, arint[i]); }

Cuidados... Um ponteiro deve sempre apontar para um local válido antes de ser utilizado Ex: void main () { int i=10, *pi; *pi = i;/*erro ! pi nao tem endereco valido*/ } void main () { int i=10, *pi = NULL; *pi = i;/*erro ! pi nao tem endereco valido*/ }

Ponteiros e Strings Quando imprimimos uma cadeia de caracteres constantes (string) com printf o que é passado é o ponteiro para a cadeia. Printf(“Ola como vai?”); Dessa forma é possível carregar o endereço da string em um ponteiro do tipo char char * lista; lista = "Ola como vai ?"; printf("%s", lista );

Ponteiros e Strings Na verdade, strings são arrays de caracteres e podem ser acessados através de char * void main () { char str[]=“abcdef”, *pc; for (pc = str; *pc != ‘\0’; pc++) putchar(*pc); } ==> abcdef o incremento de pc o posiciona sobre o próximo caracter (byte a byte)

Ponteiros e Strings Outra forma de mostrar uma string usando laço char *origem = "testando"; do{ printf("%c ", *origem); }while (*origem++); /* origem == \0 encerra o laco */ Primeiro retorna o conteúdo da posição apontada e depois incrementa a posição (precedência de operadores)

Arrays Multidimensionais Arrays podem ter diversas dimensões, cada uma identificada por um par de colchetes na declaração Ex: char multi[5][10]; declara um array de 5 linhas e 10 colunas: na memória, entretanto, os caracteres são armazenados linearmente: [0,0] [4,9] [0,9] [1,9] [0,0] [4,9]

Percorrendo array com índices: void main () { char multi[5][10]; int lin, col; for (lin=0; lin<5; lin++) for (col =0; col<10; col++) multi[lin][col] = ‘ ‘; } as colunas (dimensões mais a direita) mudam mais rápido Arrays Multidimensionais

Percorrendo array com ponteiro: void main () { char multi[5][10]; char *pc; int i; for (i=0, pc=multi[0]; i < 50; i++, pc++) *pc = ‘ ‘; } pc aponta para primeira posição do array Perceba a quantidade total de elementos

Arrays Multidimensionais Outra forma de visualizar char multi[5][10] O nome multi[5] é por si só um array indicando que existem 5 elementos, cada um deles sendo um array de 10 caracteres. multi[0] = {'0','1','2','3','4','5','6','7','8','9'} multi[1] = {'a','b','c','d','e','f','g','h','i','j'} multi[2] = {'A','B','C','D','E','F','G','H','I','J'} multi[3] = {'9','8','7','6','5','4','3','2','1','0'} multi[4] = {'J','I','H','G','F','E','D','C','B','A‘ Como os arrays são contíguos na memória, nosso bloco de memória para o array acima pode ser algo do tipo: abcdefghijABCDEFGHIJ JIHGFEDCBA inicio no endereço &multi[0][0]

Arrays Multidimensionais multi[0] = {'0','1','2','3','4','5','6','7','8','9'} multi[1] = {'a','b','c','d','e','f','g','h','i','j'} multi[2] = {'A','B','C','D','E','F','G','H','I','J'} multi[3] = {'9','8','7','6','5','4','3','2','1','0'} multi[4] = {'J','I','H','G','F','E','D','C','B','A‘ O compilador sabe quantas colunas estão presentes no array de forma que ele pode interpretar multi + 1 como o endereço do 'a' na segunda linha. Ou seja, ele acrescenta 10, o número de colunas, para obter sua posição Assim, o endereço de 9 na quarta linha acima seria &multi[3][0] ou (multi + 3) em notação de ponteiro Para obter o conteúdo do segundo elemento na quarta linha nós acrescentaríamos 1 a seu endereço e dereferenciaríamos o resultado como em *(*(multi + 3) + 1) Com um pouco de raciocínio, podemos ver que: *(*(multi + lin) + col) e multi[lin][col] dão o mesmo resultado.

Outra forma de implementar o programa anterior int main( ){ char multi[5][10]; int lin, col; for (lin=0; lin < 5; lin++) for (col=0; col < 10; col++) *(*(multi + lin) + col) = 'A'; for (lin=0; lin < 5; lin++) for (col=0; col < 10; col++) printf("%c", *(*(multi + lin) + col) ); } Arrays Multidimensionais

Array de Strings Neste caso, cada elemento do array é um ponteiro para um caracter Declaração: char *arstr[] = {“Joao”, “Maria”, “Antonio”, “Zacarias”, “Carlos”}; arstr é um array de ponteiros para char, iniciado com os strings indicados

Array de Strings Comparando array de string com array de char char *as[] = {“Joao”,“Maria”,“Antonio”,“Zacarias”,“Carlos”}; char ma[5][10] = {“Joao”,“Maria”,“Antonio”,“Zacarias”,“Carlos”}; Ponteiros (as) J o a o M a r i a A n t o n i o Z a c a r i a s C a r l o s \0 Matriz (ma)

Cuidados com Strings É comum esquecer de alocar uma área para armazenamento de caracteres void main() { char *pc; char str[] = “Um string”; strcpy(pc, str); /* erro! pc indeterminado */... }

Ponteiros Genéricos Um ponteiro genérico é um ponteiro que pode apontar para qualquer tipo de dado Define-se um ponteiro genérico utilizando-se o tipo void: void *pv; int x=10; float f=3.5; pv = &x;/* aqui pv aponta para um inteiro */ pv = &f; /* aqui, para um float */

Ponteiros Genéricos O tipo de dado apontado por um void pointer deve ser controlado pelo usuário Usando um type cast (conversão de tipo) o programa pode tratar adequadamente o ponteiro pv = &x; printf(“Inteiro: %d\n”, *(int *)pv); /*=> 10*/ pv = &f; printf(“Real: %f\n”, *(float *)pv); /*=> 3.5*/ type cast

Ponteiros para Ponteiros É possível definir ponteiros para ponteiros até um nível arbitrário de indireção Ex: char *pc;/* ponteiro para char */ char **ppc;/* ponteiro para ponteiro para char */ pc = “teste”; ppc = &pc; putchar(**ppc); /* ==> ‘t’ */

Ponteiros para Ponteiros Ponteiro para ponteiro para ponteiro... Ex: char *pc, **ppc, ***pppc; Um ponteiro permite modificar o objeto apontado ou apontar para outro objeto do mesmo tipo

Alocação dinâmica de memória Pode-se alocar dinâmicamente (em tempo de execução) um espaço de memória para uso com arrays, structs, etc... int main() { int *p; p = (int *) malloc(sizeof(int)); if (p == 0) { printf("ERRO: Sem memória\n"); return 1; } *p = 5; printf("&d\n", *p); free(p); return 0; } Aloca de forma dinâmica espaço para um inteiro

Alocação dinâmica de memória malloc Utilizamos a função malloc() quando não conseguimos prever a quantidade de memória que nosso programa irá necessitar. A função malloc() pode ser utilizada em run time para determinar o tamanho de um array. Exemplo char * p; p = malloc(50); p = (char *) malloc (sizeof (char)); free Libera memória alocada previamente Exemplo free(p);

Realocação de memória Função realloc() O realloc tenta realocar a quantidade de memória pedida na seqüência da já alocada, se não consegue, ele aloca uma nova área e retorna o ponteiro pra essa área, liberando a área previamente alocada. Declaração: void *realloc(void *ptr, size_t size); Parâmetros: Se ptr é nulo realloc() aloca o tamanaho em bytes na memória e retorna um ponteiro. Se size é zero, a memória apontada por ptr é liberada

Exemplo de realocação de memória int main() { /* aloca um espaco para 10 caracteres – 10 bytes*/ char *pointer = (char *) malloc(10 *sizeof(char)); /* realocando espaco para 20 bytes) realloc(pointer, 20); /* errado */ /* realocando espaco para 20 bytes) pointer = (char *) realloc(pointer, 20); /* certo */ return 0; } Não esquecer do casting

Alocação dinâmica de arrays void main() { int numero = 10, i; int *ar; ar = (int *) malloc(numero * sizeof(int)); for (i=0; i < numero; i++) { arr[i] = i; printf("%d \n", arr[i]); } free(arranjo); } Aloca de forma dinâmica espaço para um array de inteiros de 10 posições

int main() { int linhas, colunas, lin, col, i; int *vetor, **matriz; printf("\nDigite o numero de linhas: "); scanf("%d",&linhas); printf("\nDigite o numero de colunas: "); scanf("%d",&colunas); /****** Primeira forma de fazer vetor = (int *) malloc( linhas * colunas * sizeof(int) ); matriz = (int **) malloc( linhas * sizeof(int) ); for(i=0;i<linhas;i++) matriz[i]= &vetor[i]; */ /****** Segunda forma de fazer */ matriz= (int **) malloc( linhas * sizeof( int ) ); for(i=0;i<linhas;i++) matriz[i]= (int *) malloc( colunas * sizeof( int ) ); /*a partir deste ponto pode ser usado matriz[a][b] sendo a o número da linha e b o número da coluna para qualquer parte do programa*/ (.... Continuacao... ) /* Para demonstrar le um valor, coloca no array e depois mostra o valor da posicao */ for(col=0; col < colunas; col++) for(lin=0; lin < linhas; lin++){ printf("Informe um valor para [%d][%d]\n", lin, col); scanf("%d", &matriz[lin][col]); printf(" Valor lido-> %d\n\n“, matriz[lin][col]); } /*faz a liberação da memória alocada*/ free(vetor); free(matriz); return 0; } Aloca de forma dinâmica espaço para um array bidimensional com tamanho fornecido pelo usuário