Buscar

Tipos de Dados em Programação

Prévia do material em texto

1 
 
5185/31 e 6888/1– Paradigma de Programação Imperativa 
e Orientada a Objetos 
Profa. Valéria 
4ª Lista de Exercícios 
Cap.6 (Sebesta)/Cap.7 (Scott): Tipos de dados 
1. Dado o código abaixo, quais variáveis um compilador consideraria como tendo tipos compatíveis 
por equivalência de estrutura? E por equivalência por nome? 
type T = array [1..10] of integer 
S = T 
A : T 
B : T 
C : S 
D : array [1..10] of integer 
2. Suponha um compilador que gere código para uma máquina de 32-bits com suporte para os tipos 
char (1 byte), short (2 bytes), int (4 bytes) e float (8-byte). Suponha que as regras de alinhamento 
da máquina exigem que o endereço de cada variável de um tipo primitivo seja um múltiplo par do 
tamanho do elemento (consequentemente, todo registro terá que ser alinhado com um endereço 
múltiplo par do elemento de maior tamanho). Suponha também que o compilador não tem 
permissão para reordenar campos de registros. Quanto espaço seria usado para alocar o vetor A 
declarado abaixo? Justifique sua resposta. 
A : array [0..9] of record 
 s : short 
 c : char 
 t : short 
 d : char 
 r : real 
 i : integer 
3. Repita o exercício anterior, agora supondo que o compilador pode reordenar os campos de 
registros quando julgar necessário. 
4. Considere a seguinte declaração em C, compilada em uma máquina Pentium de 32-bits (regras de 
alinhamento semelhantes a do exercício 2): 
struct { 
 int n; 
 char c; 
} A[10][10]; 
Se o endereço de A[0][0] is 1000 (decimal), qual é o endereço de A[3][7]? 
5. Dado o código C abaixo compilado em uma máquina de 32-bits, qual será o tamanho da união 
forma? 
typedef struct { 
float diametro; 
} circulo; 
typedef struct { 
float lado1; 
float lado2; 
float lado3; 
} triangulo; 
typedef struct { 
float lado1; 
float lado2; 
} retangulo; 
 
 
 
 
typedef union { 
circulo c; 
triangulo t; 
retangulo r; 
} forma; 
 
 
 
2 
 
6. Dado o código Pascal abaixo compilado em uma máquina de 32-bits, qual será o tamanho do 
conjunto notas? 
type nota = 0..100; 
var notas: set of nota; 
7. Considere o código abaixo: 
R1 : record 
A : inteiro 
R2 : record 
 R : R1 
 B : inteiro 
Supondo uma máquina de 32-bits em que tanto um inteiro quanto uma referência ocupa 4 bytes, 
faça uma representação esquemática de como o registro R2 seria armazenado em memória se (a) a 
LP implementa variáveis por valor e (b) a LP implementa variáveis por referência. 
8. Classifique cada um dos vetores declarados abaixo de acordo com as 5 categorias propostas por 
Robert Sebesta. 
a) int main (){ 
 int vet[15]; 
 ... 
} 
b) int main (){ 
 static int vet[15]; 
 ... 
} 
 
 
c) void p1 (int y){ 
 char vet[y]; 
 ... 
} 
d) int main (){ 
 int n; 
 scanf(“%d”,&n); 
 int vet[n]; 
 ... 
} 
e) program main; 
var vet: array [1..15] of integer; 
... 
f) procedure p1; 
var vet: array [0..127] of char; 
... 
g) int main (){ 
 char *vet; 
 vet = (char *) malloc(10 * sizeof(char)); 
 ... 
} 
h) void p1 (int n){ 
 char *vet; 
 vet = (char *) malloc(n * sizeof(char)); 
 ... 
} 
9. Suponha que estamos gerando código para uma LP semelhante ao Pascal em uma máquina em que 
inteiros ocupam 4 bytes e reais ocupam 8 bytes. Suponha também que vetores multidimensionais 
serão armazenados por linha (row-major order) que os limites de índice não são checados. 
Considere as seguintes declarações de variáveis: 
var A : array [1..10, 10..100] of real; 
 i : integer; 
 x : real; 
Mostre o pseudocódigo assembly que nosso compilador geraria para a seguinte atribuição: 
x := A[3, i]. Explique como você chegou a sua resposta. 
 
 
3 
 
10. O vetor frutas pode ser declarado em C de duas formas: 
i. char *frutas = {“banana”, “pera”, “uva”, “jabuticaba”, “abacate”} 
ii. char frutas[][11] = {“banana”, “pera”, “uva”, “jabuticaba”, “abacate”} 
a) Qual é o formato de armazenamento em memória de (i) e (ii)? Represente as duas declarações 
graficamente. 
b) Quantos bytes o vetor declarado em (i) ocupará em memória em uma máquina de 32-bits? E o 
vetor declarado em (ii)? 
11. Considere a declaração abaixo: 
var r : record 
 x : integer; 
 y : char; 
 A : array [1..10, 10..20] of record 
z : real; 
B : array [0..71] of char; 
 end; 
 end; 
var j, k : integer; 
Assuma que essa declaração foi feita em um subprograma. Assuma também que os tipos char, 
integer e real ocupam, respectivamente, 1 byte, 4 bytes e 8bytes e que a máquina segue regras 
de alinhamento semelhantes as do exercício 2. Preste atenção aos limites inferiores dos índices de 
A: o primeiro elemento de A é A[1,10]. 
a) Mostre como essa declaração ficaria em memória; 
b) Mostre os cálculos necessários para acessar r.A[2,j].B[k]; 
c) Supondo que offset(r) = 12, escreva um pseudocódigo assembly para carregar 
r.A[2,j].B[k] em um registrador (offset(r) é o deslocamento que nos dá o endereço do 1º 
byte de r dentro do registro de ativação). 
12. Suponha que A é um vetor de inteiros de duas dimensões (10 x 10) armazenado em uma máquina 
de 32-bits em que tanto um inteiro quanto um ponteiro ocupa 4 bytes. Assumindo que o endereço 
de A está armazenado em r1, que i está armazenado em r2 e que j está armazenado em r3, 
escreva um pseudocódigo assembly para carregar A[i][j] em um registrador quando: 
a) A é armazenado em posições contíguas de memória; 
b) A é armazenado no formato ponteiro-linha. 
13. Explique o significado das seguintes declarações em C: 
a) double *a[n]; 
b) double (*b)[n]; 
c) double (*c[n])(); 
d) double (*d())[n]; 
14. O protótipo da função strlen definida na biblioteca string.h da linguagem C é o seguinte: 
size_t strlen ( const char * str ); 
Dada a declaração char str[10], explique por que a linha de comando (a) gera um warning 
quando compilada e (b) compila sem erros/warnings. Escreva a versão correta de (a). 
a) int tamanho = strlen(str[0]); 
b) int tamanho = strlen(str); 
15. O que resulta os comandos C abaixo? 
char str[15] = "Olá mundo!"; 
printf("%d\n", strlen(str+5)); 
16. O problema dos ponteiros pendurados (dangling references) pode persistir mesmo em LPs com 
coletor automático de lixo. Explique. 
4 
 
17. Dada a declaração do tipo recursivo list_node, explique o funcionamento das funções insert, 
reverse e delete_list. 
typedef struct list_node { 
 void* data; 
 struct list_node* next; 
} list_node; 
list_node* insert(void* d, list_node* L) { 
 list_node* t = (list_node*) malloc(sizeof(list_node)); 
 t->data = d; 
 t->next = L; 
 return t; 
} 
list_node* reverse(list_node* L) { 
 list_node* rtn = 0; 
 while (L) { 
 rtn = insert(L->data, rtn); 
 L = L->next; 
 } 
 return rtn; 
} 
void delete_list(list_node* L) { 
 while (L) { 
 list_node* t = L; 
 L = L->next; 
 free(t->data); 
 free(t); 
 } 
} 
18. Suponha que o programa principal do código do exercício anterior (17) inclua o código abaixo. Esse 
código “vaza memória”. Identifique o que está causando o vazamento de memória. 
list_node* L = 0; 
while (more_widgets()) { 
 L = insert(next_widget(), L); 
} 
L = reverse(L); 
19. O código C abaixo deveria ler um vetor de 10 elementos e imprimir o vetor em seguida, mas, 
devido a um erro, a impressão não é feita corretamente. Insira uma nova linha de código para 
corrigir o problema. 
int main(){ 
 int i; 
 int vet[10]; 
 int* pvet; 
 pvet = vet; 
 for (i=0; i<10; i++) 
 scanf("%d", pvet++); 
 for (i=0; i<10; i++) 
 printf("%d\n", *pvet++); 
} 
20. Alguns programadores sugerem que mesmo linguagenscom coletor automático de lixo deveriam 
ter um comando para desalocação explícita de memória (delete/dispose) como uma forma de se 
escrever código otimizado. Quais os “prós” e “contras” dessa sugestão.

Continue navegando