Ybadoo - Soluções em Software Livre
Turmas
2º Semestre de 2025

Considere o seguinte programa escrito na sintaxe da linguagem de programação C:

int xpto (int a, int b)
{
b = b + a;
a = b - a;
return b;
}

void main()
int v [ ] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int i = 2;
int x = xpto(v[i], i);
printf("%d", x + i);
}

Com base no programa apresentado, avalie as assertivas a seguir:

  1. Caso os parâmetros sejam passados por valor, o valor impresso será 4.
  2. Caso os parâmetros sejam passados por referência, o valor impresso será 10.
  3. Caso os parâmetros sejam passados por nome, o valor impresso será 10.
  4. Caso os parâmetros sejam passados por valor-resultado, o valor impresso será 7.

A análise permite concluir que:

a. apenas as assertivas I e II estão corretas.

b. apenas as assertivas I e III estão corretas.

c. apenas as assertivas II e III estão corretas.

d. apenas as assertivas II e IV estão corretas.

e. apenas as assertivas III e IV estão corretas.

A forma intermediária de representação com três endereços facilita a passagem do código fonte para o código alvo, e pode ser representada na notação EBNF (Extended Backus-Naur Form) . Dada a expressão area = ((base1 + base2) * altura) / 2, escrita na linguagem de programação C, que calcula a área de um trapézio, como fica a representação dessa expressão com três endereços?

a. t0 = base1; t1 = t0 + base2; t2 = altura / 2; area = t1 * t2;

b. t0 = base1 + base2; t1 = altura; area = t0 * t1 / 2;

c. t0 = base1; t1 = base2; t2 = t0 + t1; area = t2 * altura / 2;

d. t0 = base1 + base2; t1 = altura / 2 ; area = t0 * t1;

e. t0 = base1 + base2; t1 = t0 * altura; area = t1 / 2;

A notação tradicional para expressões aritméticas, que representa uma operação binária na forma x + y, ou seja, com o operador entre seus dois operandos, é conhecida como notação infixada. Uma notação alternativa para esse tipo de expressão é a notação pré-fixada, na qual o operador é expresso antes de seus operandos, como por exemplo, + x y. Outra notação alternativa é a notação pós-fixada, na qual o operador é expresso após seus operandos, como por exemplo, x y +. O atrativo das notações pré-fixada e pós-fixada é que elas dispensam o uso de parênteses ao adotar a noção de pilha para a representação das expressões. Considerando o exposto anteriormente, apresente a notação pós-fixada da expressão infixada

x = (a * b * (c * d + e) - f * (g * h + i) - (j * k + l)) / (m * (n - o))

considerando como base a gramática livre de contexto G3.

G3 = ({A, E, T, F, V}, {a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, x, =, +, -, *, /, (, )}, P3, A)
P3 = {AV = E
EE + T | E - T | T
TT * F | T / F | F
F → ( E ) | V
V → a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | x}

Sobre a representação intermediária no contexto da construção de compiladores, analise as assertivas a seguir:

  1. Representações intermediárias geralmente contêm detalhes específicos da arquitetura do sistema no qual o programa é executado.
  2. Os enunciados que aparecem no código de três endereços têm a forma geral x = y op z, nos quais x, y e z são nomes, constantes ou objetos temporários criados pelo compilador. Outras formas podem também ser usadas, incluindo desvios condicionais e incondicionais, entre outros tipos de enunciados.
  3. Autômatos finitos são usados na definição de representações intermediárias, sendo que os estados do autômato representam as variáveis do programa e as transições representam instruções do código intermediário.
  4. Árvores sintáticas e código de três endereços são dois tipos de representações intermediárias.

A análise permite concluir que:

a. apenas as assertivas I e II estão corretas.

b. apenas as assertivas I e III estão corretas.

c. apenas as assertivas II e III estão corretas.

d. apenas as assertivas II e IV estão corretas.

e. apenas as assertivas III e IV estão corretas.

A fase de otimização do código intermediário vem logo após a fase de geração desse código e tem por objetivo tornar o código intermediário mais apropriado para a produção de código objeto (código de máquina) eficiente, tanto em relação ao tamanho como ao tempo de execução. Uma das técnicas de otimização de código intermediário consiste em identificar segmentos sequencias do programa, chamados blocos básicos, e representá-los através de grafos dirigidos e submetê-los a um processo de otimização. Apresente o código de três endereços não otimizado da seguinte sequência de comandos, sobre a gramática livre de contexto G5.

x = a * b + c - d
y = e / a * b + c - d
z = a * b + e + c – d
G5 = ({A, E, T, F, V}, {a, b, c, d, e, x, y, z, =, +, -, *, /, (, )}, P5, A)
P5 = {AV = E
ET + E | T - E | T
TF * T | F / T | F
F → ( E ) | V
V → a | b | c | d | e | x | y | z}

O código objeto é criado a partir da conversão do código-fonte em linguagem de máquina, sendo criado após passar por todas as etapas de compilação e não encontrar nenhum erro no código-fonte. Para cada arquivo de código fonte é gerado um arquivo com código objeto, que posteriormente será "ligado" aos outros, através de um linker, resultando em um arquivo executável ou biblioteca. Apresente o código objeto resultante do código de três endereços otimizado obtido na Questão 05, utilizando no máximo quatro registradores (R0 a R3).

Desenvolva um programa em Simpletron Machine Language, que verifique se o número fornecido pelo usuário é um número perfeito. Um número é considerado perfeito se a soma de seus divisores próprios é igual ao próprio número, como por exemplo o número 6, cuja soma de seus divisores próprios (1 + 2 + 3) é igual a 6. Caso o número seja considerado perfeito, o programa deverá retornar 1, caso contrário, deverá retornar 0. Caso o número fornecido pelo usuário seja menor do que 2, o programa deverá retornar -1.