Aula Teórica 4: memoria dinâmica / pre-processador Departamento de Informática, UBI
C(ontiguous) alloc Calloc A função calloc permite de criar um espaço de memória contíguo com uma dimensão certa calloc(n, elem-bytes) n é a dimensão elem-bytes é o numero de bytes de cada elemento Todos os bits são fixados a 0 Exemplo: seja a um apontador, int a; a = calloc(n, sizeof(int)); Notam: para utilizar tem de incluir a biblioteca stdlib.h
M(emory) alloc Malloc A função malloc cria um espaço de memoria com uma dimensão certa malloc(s) s é a dimensão em bytes Notam: o valor inicial não e inicializado Exemplo: int a; a = malloc(n sizeof(int)); Se queremos um array de dimensao 3 e cada inteiro ocupa 4 bytes... a = malloc(12); A função é também incluída na biblioteca stdlib.h
Liberar a memoria Free A memoria ocupada com calloc ou malloc tem de ser libertada explicitamente Este mesmo se o programa encontra um exit ou um return Fazemos isso com o comando free a = malloc(12);... free(a); IMPORTANTE: se tentamos de libertar uma memoria já livre, há um erro Exemplo: a = malloc(12); free(a); free(a); //erro So e possivel fazer o free uma vez de um apontador criado com a calloc/malloc Exemplo: int a; free(a); //erro
Copiar um array ate um limite Problema Temos um array A e queremos copiar so uma parte de A em um array B Especificao: queremos (re-)utilizar uma função que faz isso para tamanhos arbitrários Idea: utilizamos a malloc para criar um array B com dimensão n Assim não gastamos espaço inutilmente Onde criar o array? Lembram: os arrays sao passados para referencia Criamos o array fora da função Passamos o dois arrays a a função e o tamanho deles
Copiar um array ate um limite #include<stdio.h> //#include<stdlib.h> void copyarray (int a[], int m, int b[], int n) // m is the size of a, n is the size of b { int i,j; if (n>m) exit(0); else for (i=0;i< n; ++i) b[i]=a[i]; int main() { int a[10]={10,4,3,2,7,7,1,3,9,11,*b,n=3,i; b= malloc(n * sizeof(int)); copyarray(a,10,b,n); for (i=0; i <n; ++i) printf("b[%d] is: %d\n",i,*(b+i)); return (1);
Main com parametros Main Em programas assim é pratico poder passar parâmetros ao main, por exemplo: o tamanho do array de destinação Como fazer? int main(int argc, char argv[]) argc e o numero de parametros (incluindo o main) argv sao os parametros argv[0] e o nome do programa argv[1] e o primeiro parâmetro...
Main com parametros Main Os parâmetros são "string" Para utilizar cada parâmetro talvez e util transformar em int A função que faz isso e "atoi", na biblioteca stdlib.h int main(int argc, char argv[]) int primeiro-par=atoi(argv[1]); E boa pratica controlar antes se o numero de parâmetros é certo if (argc == 2)...
Copiar um array ate um limite #include<stdio.h> #include<stdlib.h> void copyarray (int a[], int m, int b[], int n) // m is the size of a, n is the size of b { int i,j; if (n>m) exit(0); else for (i=0;i< n; ++i) b[i]=a[i]; int main(int argc, char *argv[]) { int a[10]={10,4,3,2,7,7,1,3,9,11,*b,n,i; if (argc!= 2) exit (0); else { n=atoi(argv[1]); if (n>10) n=10; b= malloc(n * sizeof(int)); copyarray(a,10,b,n); for (i=0; i <n; ++i) printf("b[%d] is: %d\n",i,*(b+i)); return (1);
Recapitular: Bubble sort Ordenação de um array Algoritmo intuitivo mais custoso para ordenar um array Especifica do problema: dato um array ade inteiros ordenar o array em modo crescente O elemento a[0] e o elemento minimo a[dim] e o maximo Ideia: confrontar todos os elementos adjacentes e fazer o swap quando o elemento na direita e minor do elemento na ezquerda Quando acabar? Quando todos os elementos são ordenados Pode precisar mais passos
Codigo para o Bubblesort com parametros #include<stdio.h> #include<stdlib.h> void swap(int *x, int *y); void bubble (int a[], int n) // n is the size of a { int i,j; for (i=0;i< n-1; ++i) for (j=n-1; j>i; --j) if (a[j-1] > a[j]) //swap (&a[j-1], &a[j]); swap (a+(j-1),a+j); int main(int argc, char *argv[]) { int *a=malloc(argc * sizeof(int)),i; for (i=1; i<argc; ++i){ a[i]=atoi(argv[i]); printf("a[%d] is %d\n",i,atoi(argv[i])); if (argc!= 1) bubble (a,argc); else exit(0); for (i=1; i < argc; ++i) printf("now a[%d] is: %d\n",i,*(a+i)); free(a); return 1;
Pre-processador Include Ja utilizamos uma directiva do pre-processador o #include permite de incluir o conteúdo de um ficheiro Exemplo: #include <stdio.h> faz o replace da linha com o conteúdo do ficheiro "stdio.h" Notam que este e o path relativo do ficheiro E.g. em sistemas UNIX o path completo e obtenido fazendo o concat com "/usr/include/" Mas pode ser um ficheiro C qualquer, mesmo contendendo outras directivas
Pre-processador Define A forma mas tipica é #define identifier token-string Exemplo: #define PI3.14159 Exemplo: #define EQ == while (i EQ 1){... O pro-processador vais sostituir o EQ com == Aumenta a portabilidade
Pre-processador Define Exemplos #define identifier token-string #define EOF 1 #define MAXINT2147483647 #define ITERS50 #define MAXSIZE250
Pre-processador Define O define pode utilizar parametros #define identifier (identifier,..,identifier) token-string Exemplo: #define SQ(x)((x) (x)) SQ(7 + w) é ((7 + w) (7 + w)) SQ(SQ( p) é (((( p) ( p))) ((( p) ( p)))) Notam as parênteses! Exemplo (errado): #define SQ(x)((x) (x)) SQ(a + b) é a + b a + b
Pre-processador Define Notam: no define não tem de inserir o ";"no final!!! #define identifier (identifier,..,identifier) token-string Exemplo (errado): #define SQ(x)((x) (x)); y = SQ(z); é y = ((z) (z)); ; //NULL STATEMENT if (x == 1) y = SQ(z); else...//error O comando null nao permite o uso do else
Pre-processador Define e funções O define pode ser utilizado para sostituir funções #define identifier (identifier,..,identifier) token-string Exemplo : #define MIN(x, y)(((x) < (y))?(x) : (y)) y = min(z, w); é y = (((z) < (w))?(z) : (w)); Exemplo : #define min4(x, y, z, w) MIN(MIN(x, y), MIN(z, w)) NOTAM: o debugging pode ser complexo Para ver o output do pre-processador: cc -E file.c
Codigo exemplo #include <stdio.h> #define message_for(a, b) \ printf(#a " and " #b ": We love you!\n") int main(void) { message_for(carole, Debra); return 0;
Codigo exemplo #include <stdio.h> #undef PIE #define PIE "I like apple." int main(void) { printf("pie: " PIE "\n"); return 0;
Codigo exemplo #include <stdio.h> #include <stdlib.h> /* for abort() */ #if defined(ndebug) #define assert(ignore) ((void) 0) /* ignore it */ #else #define assert(expr) \ if (!(expr)) { \ printf("\n%s%s\n%s%s\n%s%d\n\n", \ "Assertion failed: ", #expr, \ "in file ", FILE, \ "at line ", LINE ); \ abort(); \ #endif int main(void) { assert(1 > 2); return 0;