Você está na página 1de 7

Lista 2

Linguagem de Programação

Capı́tulo 6 - Tipos de Dados

1. A utilização indiscriminada dos ponteiros genéricos podem provocar vários erros de tipos. No seguinte trecho de código, temos um
exemplo de um erro causado pelos ponteiros genéricos que é encontrado em tempo de compilação. Explique como acontece esse erro.

1 int f , g;
2 void ∗ p ;
3 f = 10;
4 p = &f ;
5 g = ∗p ; // e r r o r : ’ v o i d ∗ ’ i s not a p o i n t e r −to−o b j e c t t y p e

2. O tipo apontado por um ponteiro não é restrito. Logo, expressões contendo ponteiros podem ser avaliadas com valores diferentes do
esperado originalmente provocando erros em tempo de execução. Explique porque a expressão *p + 5 pode provocar um erro em
tempo de execução.

1 i n t i , j = 10;
2 p = &j ;
3 p++;
4 i = ∗p + 5 ;

3. Ponteiros são causadores potenciais de erros em programação. Dê exemplos, com trechos de código em C, de erros causados por
ponteiros que provocam ocorrência de objetos pendentes e ocorrência de referências pendentes.

4. Em geral, a verificação de uso de ı́ndice fora dos limites do vetor só pode ser verificado em tempo de execução. Algumas LPs, como
JAVA, PASCAL e MODULA-2 fazem a verificação dinâmica dos ı́ndices. Outras, como C, C++ e FORTRAN não fazem essa verificação.
Justifique porque algumas LPs adotaram uma postura e outras adotaram uma postura oposta

5. Considere o seguinte programa escrito em C++:

1 #i n c l u d e <i o s t r e a m >
2 i n t & xpto ( i n t s i n a l ) {
3 i n t p = 4;
4 i f (! sinal ) {
5 p∗= s i n a l ;
6 } else {
7 p++;
8 }
9 return p ;
10 }
11 v o i d ypto ( ) {
12 i n t c [1000];
13 i n t aux ;
14 f o r ( aux = 0 ; aux < 1000; aux++) {
15 c [ aux ] = aux ;
16 }
17 }
18
19 main ( ) {
20 i n t a = 1;
21 i n t & b = xpto ( a ) ;
22 ypto ( ) ;
23 c o u t << b ;
24 }

Determine quais serão as saı́das possı́veis do programa acima. Explique sua resposta

1
6. Listas heterogêneas são estruturas de dados capazes de armazenar no seu campo de informação valores de tipos distintos. Uma
forma de implementar listas heterogêneas em C é através do uso de uniões. Outra forma é através do uso de ponteiros para void.
Mostre, através de exemplos de código em C, como se pode fazer para definir listas heterogêneas usando essas duas abordagens (não
é preciso implementar as operações de lista, apenas a definição da estrutura de dados). Compare e discuta essas soluções em termos
de redigibilidade (das operações da lista) e flexibilidade (em termos de necessidade de recompilação do módulo lista quando for
necessário alterar ou incluir um novo tipo de dado no campo informação).

7. Muito embora JAVA seja fortemente influenciada por C, os projetistas dessa LP resolveram incluir o tipo boolean, o qual não existe em
C. Explique porque essa decisão foi tomada. Dê exemplo de situação na qual a postura de C traz alguma vantagem. Faça o mesmo em
relação a postura de JAVA. Justifique suas respostas.

8. Analise e escreva uma comparação das funções malloc e free do C com os operadores new e delete de C++. Use a segurança como a
consideração primária na comparação.

1 #i n c l u d e < b i t s / s t d c++.h>
2
3 u s i n g namespace s t d ;
4

5 i n t main ( ) {
6 try {
7 i n t ∗ v1 = new i n t [ 5 ] ;
8 d e l e t e [ ] v1 ;
9 } c a t c h ( s t d : : b a d a l l o c& ba ) {
10 s t d : : c e r r << ” b a d a l l o c caught : ” << ba . what ( ) << ’ \n ’ ;
11 };
12
13 i n t ∗ v2 = ( i n t ∗) m a l l o c ( 5∗ s i z e o f ( i n t ) ) ;
14 i f ( v2 == NULL ) {
15 p r i n t f ( ” Memoria i n s u f i c i e n t e \n ” ) ;
16 e x i t (1) ;
17 }
18 f r e e ( v2 ) ;
19
20 }

Dica:

(a) Analise o retorno do operador new e da função malloc.


(b) Analise a necessidade da função sizeof.
(c) Analise como cada um trata a condição de falha de alocação.

Capı́tulo 7 - Expressões e Sentenças de Atribuição

1. Descreva o que ocorre em cada trecho que culmina com impressões no seguinte programa em C:

1 #i n c l u d e <s t d i o . h>
2 v o i d main ( ) {
3 int a , b , c ;
4 b = c = 10;
5 a = b++ + b++;
6 p r i n t f ( ”%d\n ” , a ) ;
7 p r i n t f ( ”%d\n ” , b ) ;
8 a = ++c + ++c ;
9 p r i n t f ( ”%d\n ” , a ) ;
10 p r i n t f ( ”%d\n ” , c ) ;
11 b = 10;
12 a = b++ + b ;
13 p r i n t f ( ”%d\n ” , a ) ;
14 p r i n t f ( ”%d\n ” , b ) ;
15 a = 10;
16 b = 5;
17 i f ( a>b | | ++b>5)
18 p r i n t f ( ”%d\n ” , b ) ;
19 a = 1;
20 b = 5;
21 i f ( a>b | | ++b>5)
22 p r i n t f ( ”%d\n ” , b ) ;
23 }

2. Analise o seguinte programa em C, identificando o que ele faz. Faça uma crı́tica a esse código.

2
1 #i n c l u d e <s t d i o . h>
2 main ( ) {
3 int i , j , k;
4 k = 1;
5 f o r ( i = 0 ; i < 10; i++) {
6 entra :
7 j = 2 ∗ i + 1;
8 p r i n t f ( ” i : %d , j : %d\n ” , i , j ) ;
9 }
10 i f (k) {
11 k = 0;
12 i = 7;
13 goto e n t r a ;
14 }
15 }

3. Algumas LPs (tal como, C) consideram a operação de atribuição como sendo uma espécie de expressão (isto é, a atribuição é uma
operação que retorna um valor). Dê exemplos de situações nas quais isso pode ser vantajoso. Diga também quando essa caracterı́stica
pode ser danosa para a qualidade da programação. Justifique sua resposta utilizando os trechos de código abaixo:

1 void s t r i n g c o p y ( char ∗ p , char ∗ q) {


2 w h i l e (∗ p++ = ∗q++);
3 }
4 ...
5 w h i l e ( i = 10) {

4. Assuma as seguintes regras de associatividade e de precedência para expressões:


Precedência Mais alta *, /, not
+, -, &, mod
- (unário)
=, / =, <, <=, >=, >
and
Mais baixa or , xor
Associatividade Esquerda para a direita
Mostre a ordem de avaliação das seguintes expressões por meio do uso de parên- teses em todas as subexpressões e colocando um
expoente no parêntese direito para indicar a ordem. Por exemplo, para a expressão

a+b∗c+d (1)

a ordem de avaliação seria representada como


((a + (b ∗ c)1 )2 + d)3 (2)

(a) a * b - 1 + c
(b) a * (b - 1) / c mod d
(c) (a - b) / c & (d * e / a - 3)
(d) -a or c = d and e
(e) a > b xor c or d <= 17
(f) -a + b

5. Considere que a função fun é definida como

1 i n t fun ( i n t ∗k ) {
2 ∗k += 4 ;
3 r e t u r n 3 ∗ (∗ k ) − 1 ;
4 }

Suponha que fun seja usada em um programa, como:

1 v o i d main ( ) {
2 i n t i = 10 , j = 10 , sum1 , sum2 ;
3 sum1 = ( i / 2) + fun (& i ) ;
4 sum2 = fun (& j ) + ( j / 2) ;
5 }

Quais são os valores de sum1 e sum2

(a) Se os operandos na expressão forem avaliados da esquerda para a direita?


(b) Se os operandos na expressão forem avaliados da direita para a esquerda?

3
Capı́tulo 8 - Estruturas de Controle no Nı́vel de Sentença

1. Reescreva o seguinte segmento de pseudocódigo usando uma estrutura de laço na linguagem C:

1 k = ( j + 13) / 27
2 loop :
3 i f k > 10 then goto out
4 k = k + 1
5 i = 3 ∗ k − 1
6 goto loop
7 out : . . .

2. Reescreva o seguinte segmento de código usando uma sentença de seleção múltipla nas seguintes linguagens:

1 if ( ( k==1) || ( k==2)) j = 2∗k − 1


2 if ( ( k==3) || ( k==5)) j = 3∗k − 1
3 if ( ( k==4) ) j = 4∗k − 1
4 if ( ( k==6) || ( k==7) | | ( k==8)) j = k−2

(a) Fortran95
(b) Ada
(c) C

3. Em uma carta para o editor da CACM, Rubin (1987) usa o seguinte segmento de código como evidência de que a legibilidade de algum
código com gotos é melhor do que o código equivalente sem gotos. Esse código encontra a primeira linha de uma matriz inteira n por
n chamada x que não tem nada além de valores iguais a zero.

1 f o r ( i = 1 ; i <= n ; i++) {
2 f o r ( j = 1 ; j <= n ; j++){
3 i f ( x [ i ] [ j ] != 0)
4 goto r e j e c t ;
5 }
6 p r i n t l n ( ’ F i r s t a l l −z e r o row i s : ’ , i ) ;
7 break ;
8 reject :
9 }

Reescreva esse código sem gotos em uma das seguintes linguagens: C, C++, Java, C# ou Ada. Compare a legibilidade de seu código
com o do exemplo.

4. Considere o seguinte segmento de programa em C. Reescreva-o sem usar gotos ou breaks.

1 j = −3;
2 f o r ( i = 0 ; i < 3 ; i++) {
3 s w i t c h ( j + 2) {
4 case 3:
5 c a s e 2 : j −−; break ;
6 c a s e 0 : j += 2 ; break ;
7 d e f a u l t : j = 0;
8 }
9 i f ( j > 0) break ;
10 j = 3 − i
11 }

5. O comando goto é empregado para realizar desvios incondicionais no fluxo de controle de programas. Com o advento das técnicas
de programação estruturada, este comando foi muito criticado e, por muitas vezes, se sugeriu que linguagens de programação não
deveriam incluı́-lo entre seus comandos. C é uma linguagem que adota os princı́pios da programação estruturada. No entanto, C
manteve o goto como um comando da linguagem. Qual a razão dessa decisão? Exemplifique, comum trecho de programa em C, uma
situação na qual pode ser útil empregar o comando goto.

Capı́tulo 9 -Subprogramas

1. Quais são os argumentos a favor e contra um programa de usuário construir definições adicionais para operadores existentes, como
pode ser feito em Ada e C++? Você acredita que tal sobrecarga de operadores definida pelo usuário é boa ou ruim? Justifique sua
resposta.

2. Apresente um argumento contra fornecer tanto variáveis locais estáticas quanto dinâmicas em subprogramas.

3. Considere o programa escrito na sintaxe de C:

4
1 v o i d swap ( i n t a , i n t b ) {
2 i n t temp ;
3 temp = a ;
4 a = b;
5 b = temp ;
6 }
7 v o i d main ( ) {
8 i n t v a l u e = 2 , l i s t [ 5 ] = {1 , 3 , 5 , 7 , 9 } ;
9 swap ( value , l i s t [ 0 ] ) ;
10 swap ( l i s t [ 0 ] , l i s t [ 1 ] ) ;
11 swap ( value , l i s t [ v a l u e ] ) ;
12 }

Para cada um dos métodos de passagem de parâmetros, quais são todos os valo- res das variáveis value e list após cada uma das três
chamadas a swap ?

(a) Passadas por valor


(b) Passadas por referência

Capı́tulo 10 -Implementando Subprogramas

1. Mostre a pilha com todas as instâncias de registro de ativação, incluindo o en- cadeamento estático e o dinâmico, quando a execução
alcança a posição 1 no seguinte esqueleto de programa. Assuma que Bigsub está no nı́vel 1

1
2 procedure Bigsub i s
3 procedure A i s
4 procedure B i s
5 b e g in −− de B
6 . . . <−−−−−−−−−−−−−−−−−−−1
7 end ; −− de B
8 procedure C i s
9 b e g in −− de C
10 ...
11 B;
12 ...
13 end ; −− de C
14 b e g in −− de A
15 ...
16 C;
17 ...
18 end ; −− de A
19 b e g in −− de Bigsub
20 ...
21 A;
22 ...
23 end ; −− de Bigsub

2. Mostre a pilha com todas as instâncias de registro de ativação, incluindo o encadeamento estático e o dinâmico, quando a execução
alcança a posição 1 no seguinte esqueleto de programa. Assuma que Bigsub está no nı́vel 1.

1 procedure Bigsub i s
2 MySum : F l o a t ;
3 procedure A i s
4 X : Integer ;
5 procedure B(Sum : F l o a t ) i s
6 Y, Z : Float ;
7 b e g in −− de B
8 ...
9 C(Z)
10 ...
11 end ; −− de B
12 b e g in −− de A
13 ...
14 B(X) ;
15 ...
16 end ; −− de A

5
17 procedure C( Plums : F l o a t ) i s
18 b e g in −− de C
19 . . . <−−−−−−−−−−−−−−−−−−−1
20 end ; −− de C
21 L : Float ;
22 b e g in −− de Bigsub
23 ...
24 A;
25 ...
26 end ; −− de Bigsub

3. Mostre a pilha com todas as instâncias de registro de ativação, incluindo o encadeamento estático e o dinâmico, quando a execução
alcança a posição 1 no seguinte esqueleto de programa. Assuma que Bigsub está no nı́vel 1.

1 procedure Bigsub i s
2 procedure A( F l a g : Boolean ) i s
3 procedure B i s
4 b e g in −− de B
5 ...
6 A( f a l s e ) ;
7 end ; −− de B
8 b e g in −− de A
9 i f f l a g then B ;
10 else C;
11 ...
12 end ; −− de A
13 procedure C i s
14 procedure D i s
15 b e g in −− de D
16 . . . <−−−−−−−−−−−−−−−−−−−−−1
17 end ; −− de D
18 b e g in −− de C
19 ...
20 D;
21 end ; −− de C
22
23 b e g in −− de Bigsub
24 ...
25 A( t r u e ) ;
26 ...
27 end ; −− de Bigsub

A sequência de chamadas para esse programa para que a execução alcance D é

(a) Bigsub chama A


(b) A chama B
(c) B chama A
(d) A chama C
(e) C chama D

4. Mostre a pilha com todas as instâncias de registro de ativação, incluindo o encadeamento dinâmico, quando a execução alcança a
posição 1 no seguinte esqueleto de programa. Esse programa usa o método de acesso profundo para implementar o escopo dinâmico.

1
2 v o i d fun1 ( ) {
3 float a;
4 ...
5 }
6 v o i d fun2 ( ) {
7 int b , c ;
8 ...
9 }
10 v o i d fun3 ( ) {
11 float d;
12 . . . <−−−−−−−−−−−−−−−−−−−−−1
13 }
14 v o i d main ( ) {

6
15 char e , f , g ;
16 ...
17 }

A sequência de chamadas para esse programa para que a execução alcance fun3 é
main chama fun2
fun2 chama fun1
fun1 chama fun1
fun1 chama fun3

5. Desenhe a pilha de registros de ativação, incluindo o endereço de retorno e as cadeias estática e dinâmica, quando a execução atinge
o ponto marcado com # no seguinte esqueleto de programa ADA

1 procedure Main i s
2 x : integer ;
3 procedure A ;
4 y : integer ;
5 procedure B ( k : boolean ) ;
6 w: i n t e g e r ;
7 b e g in −− B
8 i f k then B ( f a l s e ) ;
9 e l s e −− #;
10 end B ;
11 procedure C ;
12 z : integer ;
13 b e g in −− C
14 ...
15 B ( true ) ;
16 end C ;
17 b e g in −− A
18 ...
19 C;
20 ...
21 end A ;
22 b e g in −− Main
23 ...
24 A;
25 end Main ;

Você também pode gostar