Aula Teórica 4: memoria dinâmica / pre-processador
Marco Giunti
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));
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
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 Marco Giunti Programação II
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
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; }
void swap(int *x, int *y) {
/* int temp = *x; /save the value at address x */ *x = *x+*y; /* put x+y into x */
*y = *x-*y; /* put x-y = argument x into y */ *x = *x-*y; /* put x-y = argument y into y */ }
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
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
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; }