Baixe o app para aproveitar ainda mais
Prévia do material em texto
Paradigmas de linguagens de programação Aula 4: Amarrações Apresentação Uma linguagem de programação usa o conceito de entidades para designar elementos da linguagem, como, por exemplo, variáveis, constantes, subprogramas (rotinas ou funções), parâmetro dos subprogramas e comandos. A amarração é um conceito central usado na descrição de várias propriedades semânticas de linguagens de programação (LPs). Registraremos nesta aula tais propriedades, identi�cando tanto o tempo quanto o ambiente de amarração. Objetivos Ilustrar conceito de amarração; Identi�car tempo de amarração e as diferentes implementações em LPs; De�nir ambiente de amarração e o escopo de visibilidade dos identi�cadores. Conceito de amarração Amarração é uma associação entre entidades de programação, como, por exemplo, entre uma variável e seu valor ou entre o identi�cador de uma variável e o seu tipo de dado (conjunto de valores que a variável poderá armazenar). Ela pode ser: Estática Se for estabelecida antes da execução do programa, não podendo ser alterada. Dinâmica Se acontecer em tempo de execução, podendo sofrer mudanças. Os conceitos de amarração e tempo de amarração são úteis para se entender a semântica das LPs. O ambiente de amarração de�ne o escopo de visibilidade dos identi�cadores. Seus conceitos serão expostos a seguir. Conceitos Clique no botão acima. Conceitos Identi�cadores Em uma linguagem de programação (LP), o identi�cador é um nome (cadeia de caracteres) que referencia as entidades de um programa. O nome adequado de um identi�cador deve nos remeter rapidamente à lembrança de sua �nalidade: referenciar variáveis (locais ou globais), procedimentos, funções e outros elementos do programa, que são as entidades. As LPs implementam o identi�cador de diferentes formas. Um aspecto relevante associado à implementação do identi�cador é o uso da propriedade case sensitive, que faz a distinção entre identi�cadores escritos com letras minúsculas e maiúsculas. Nesse caso, a LP vai permitir que um mesmo nome referencie mais de uma unidade distinta, podendo di�cultar o entendimento do programa (legibilidade). O programador, portanto, terá de lembrar a escrita exata do identi�cador de cada entidade. Por exemplo, Identidade e identidade são identi�cadores distintos que referenciam entidades diferentes. Nas linguagens que não implementarem o case sensitive, poderemos, por exemplo, ter um identi�cador de variável denominado Nome, outro chamado nome e ainda um terceiro NOME – e os três farão referência à mesma entidade. Isso pode gerar um problema de legibilidade e entendimento do código, pois teremos os mesmos nomes com diferentes variações de letras maiúsculas e minúsculas para referenciar a mesma entidade. As linguagens C, C++, Modula-2 e Java são case sensitive. No C, por exemplo, esse problema pode ser contornado se forem usadas exclusivamente letras minúsculas para os nomes. Já em Java, essa possibilidade não existe. Para converter uma cadeia de caracteres (string) em inteiro dentro do C, é usada a função (prede�nida) de nome parseInt. Se o programador tentar usar a função escrevendo parseint ou Parseint, não terá sucesso. As linguagens Ada, Pascal e Delphi, por sua vez, não são case sensitive. Dessa forma, ao referenciar o identi�cador de variável Nome e o identi�cador nome, ou NOME, ou ainda qualquer combinação de maiúsculas e minúsculas, o programador fará referência à mesma entidade. Os identi�cadores devem ter nomes autoexplicativos que lembrem rapidamente a entidade que eles referenciarem, devendo-se manter um estilo consistente e padronizado para nomear identi�cadores e aumentar a legibilidade e a compreensão do código. Dica: pode-se usar apenas a primeira letra maiúscula e as demais minúsculas, como Nome, Telefone, Sexo etc. Identi�cadores especiais Além dos identi�cadores criados pelos programadores para referenciar entidades (variáveis, nomes de subprogramas e parâmetros), temos aqueles que vão identi�car os símbolos e as palavras especiais da própria linguagem: a) Palavras reservadas Identi�cadores usadas pela LP, em geral, para uma �nalidade especí�ca: eles não podem ser usados pelo programador para outro �m. Não será possível, assim, a utilização deles como identi�cadores de entidades. Por exemplo, em Java, o programador não pode usar o nome For como identi�cador de uma variável, pois é uma palavra reservada. Ainda em Java, também temos como exemplo os termos Const e goto, que são palavras reservadas: elas não têm signi�cado para a linguagem, não podendo ser usadas por programadores para referenciar identi�cadores de entidades. Isso garante que, em futuras versões, caso a linguagem venha a implementar um uso para esses termos, o código já escrito não tenha impacto. b) Palavras-chave Símbolos da LP que têm um signi�cado especial para a linguagem. Algumas LPs, como, por exemplo, Fortran, permitem que palavras-chave sejam usadas pelo programador como um identi�cador de entidades. Por exemplo, podemos observar em Fortran o seguinte dado obtido pelo código composto das duas linhas a seguir: linha 1: INTEGER Num e linha 2: INTEGER = 12. Na linha 1, temos a de�nição da variável de nome Num, do tipo INTEGER (inteiro). Sendo assim, a palavra-chave INTEGER foi usada, nesse caso, como um tipo de dado. Já na linha 2, temos o mesmo identi�cador INTEGER denotando, agora, uma variável que recebe 12 como conteúdo. Observou a confusão que isso pode causar ao se tentar ler um código usando tal artifício? Isso afeta a legibilidade do código. Amarração ( ) Quando escrevemos programas de computador, fazemos referências a muitas coisas nas linhas de código: Variáveis (abstração da memória RAM); Subprogramas (unidades de programação como procedimentos e funções); Parâmetros para os subprogramas; Comandos da linguagem; Operações; Tipos de dados. a) Referências Acessos ao nome de cada coisa, que chamaremos de entidade. b) Entidades Podem ser: Identi�cadores (nome dado às entidades); Símbolos (elementos da linguagem de programação); Palavras especiais (palavras reservadas, palavras-chave e funções prede�nidas) da LP. c) Identi�cadores São os nomes dados a: Variáveis; Subprogramas; Parâmetros dos subprogramas. d) Símbolos Operação: Por exemplo, aritmética (+, -, *, /, soma, subtração, multiplicação e divisão); Operador: Lógico (and, or e not) e relacionado (=, <, <=, >, >= e <>); Palavra especial da linguagem: Palavras reservadas (comandos da linguagem e tipos de dados, como int, char, �oat e boolean). O conceito de amarração, binding ou vinculação está intimamente relacionado com a associação entre entidades de programação (variáveis, procedimentos, funções, comandos etc.) e símbolos da linguagem. Como exemplo, podemos citar a vinculação entre um identi�cador de variável e seu valor ou entre um identi�cador de variável e seu tipo (conjunto de valores que podem ser armazenados). (Fonte: REDPIXEL.PL / Shutterstock). O foco está na amarração (associação) dos identi�cadores às entidades. Atenção! Aqui existe uma videoaula, acesso pelo conteúdo online Tempos de amarração A amarração pode acontecer em momentos distintos dependendo do caso. A esse momento, chamamos de tempo de amarração. Observe a tabela a seguir com algumas entidades e seus respectivos tempos ou momentos de amarração. Identificador ou símbolo Entidade Tempo de amarração Operandos e seus comportamentos * (multiplicação) Em tempo de projeto da LP Palavras reservadas e comportamento Char, boolean, if, while, Perform, sqrt Em tempo de projeto da LP Faixa de valores Tipo de dado Em tempo de implementação do compilador ou projeto da LP Variável: Associação da variável a seu tipo Tipo Em tempo de compilação Operadores: Associar expressões com seus operadores Expressões Em tempo de compilação Procedimento Código do procedimento Na fase de ligação do processo de tradução Variável global Variável (memória RAM) Na carga do programa Comando de atribuição de valor Variável Em tempo de execução Tabela: Amarração × tempo de amarração. a) Variável Tem como atributos: 1 Nome (identi�cador) 2 Tipo de dados (inteiro, texto, com decimal, alta precisão etc.) 3 Posição de memória 4 Valor (varia em função de atribuição de valores ou de atribuição do resultado deexpressões) A amarração será do identi�cador da variável a seu endereço de memória, o que será resolvido (com a ajuda do sistema operacional) quando o programa estiver sendo carregado na memória para ser executado. Nesse momento, com base na tabela de símbolos (mantida pelo sistema operacional) e no tipo de dado da variável, o sistema operacional aloca o endereço para cada variável global (no contexto do programa principal). Isso ocorre em LPs fortemente tipadas, nas quais é factível o cálculo de endereçamento da variável com base na quantidade de bytes usados para armazenar cada tipo de dado possível de�nido pela linguagem. b) Variável global De�nida no nível do programa principal. Todas as rotinas podem ter acesso a ela desde que isso não �ra alguma regra de implementação da visibilidade da LP. A amarração de uma variável global ocorre quando o programa for carregado na memória para a sua execução. c) Variável local Criada dentro de uma rotina, ela somente pode ser acessada dentro do contexto dessa rotina. Uma variável local pertence a uma das unidades do programa (subprogramas) e somente pode ser acessada no contexto dessa unidade em que a variável tem vida (ou seja, em que ela exista de fato). O endereçamento dessa variável deve ser em tempo de execução. Quando o programa for executado, a unidade será acionada pelo programa principal ou por outra unidade. Os tempos de amarração possíveis são: Clique nos botões para ver as informações. Quando forem de�nidas as amarrações determinadas na própria LP. 1. Tempo de projeto da LP Quando o compilador for construído e implementado, dando vida às regras da LP (sintática e semântica). 2. Tempo de implementação do compilador Durante o processo de tradução da LP, a compilação é uma das fases de tradução do código em LP de alto nível para linguagem de máquina. 3. Tempo de compilação do programa Fase de ligação ou linkedição do processo de tradução da LP. 4. Tempo de ligação do programa Quando o programa for carregado na memória momentos antes de ser executado. 5. Tempo de carga do programa Durante o período em que o programa estiver em execução. 6. Tempo de execução do programa Cada amarração está associada a um determinado escopo, ou seja, à região (e ao momento) do programa em que a entidade é visível. A amarração pode ser: Estática Quando ela acontecer antes da execução do programa, permanecendo sem possibilidade de ser alterada em tempo de execução. Dinâmica Quando ela ocorrer durante a execução do programa, podendo ser criada e alterada. Comentário Quanto antes a amarração ocorrer, maior será a e�ciência da execução (pode-se otimizar o código) e menor a sua �exibilidade (ela não pode ser alterada conforme o projeto da LP). Ter um claro entendimento das amarrações e de seus tempos é parte do conhecimento necessário para compreender a semântica das LPs. Ambientes de amarração Um ambiente de amarração compreende um conjunto de amarrações que determinam o que os identi�cadores denotam ao longo do código. Os comandos e as expressões de um programa são avaliados dentro de um determinado ambiente cujos identi�cadores devem ter sido amarrados. Se identi�carmos comandos e expressões iguais em pontos distintos do programa, pode ser que haja diferentes interpretações. Contudo, dentro de um mesmo ambiente, permite-se apenas uma amarração por identi�cador, salvo algumas exceções à regra, como é o caso da linguagem C++. Observe o trecho de código abaixo com amarração do mesmo identi�cador (variável a) a duas entidades distintas em mesmo ambiente: int num = 15; {int aux = num; int num = 2; aux = aux + num; )} Na linha 1, temos a variável global num recebendo o valor 15 como conteúdo; na linha 4, a variável local, de nome num, no contexto do bloco do procedimento F, também é do tipo inteiro e recebe o valor 2. Portanto, um identi�cador (no exemplo acima, num) refere-se a variáveis distintas em diferentes ambientes (variável global e variável local), o que pode vir a confundir quem estiver lendo, afetando diretamente a legibilidade do código. Avalie o código abaixo escrito em Pascal. As linhas 001 a 018 não existem na sintaxe da linguagem. Elas foram inseridas para facilitar os comentários: 001 Program Amarracao; 002 Var Num: integer; 003 004 Procedure P1_Amarracao; 005 Var Num, Tot: integer; 006 Begin 007 Tot:=0; 008 Num:=2; 009 Tot:=Tot + Num; 010 Writeln (`Dentro de P1_amarracao:`,’Num: `,Num,`Tot: `,Tot); 011 End; 012 013 Begin (* programa principal *) 014 Num:=13; 015 Writeln (`Num Antes P1_amarracao: `,Num); 016 P1_Amarracao; 017 Writeln (‘Num Pos P1_amarracao: `,Num); 018 End. Observemos o código do programa acima: nas linhas 002 e 005, temos duas declarações do identi�cador Num. Observe que ambas estão em contextos diferentes. No identi�cador da linha 002, temos uma variável global; já na 005, o mesmo identi�cador é uma variável local ao procedimento P1_amarracao. O valor do identi�cador depende do contexto de sua utilização e das possíveis amarrações. Já os comandos Writeln estão no contexto de: P1_amarracao: Linha 010; Programa principal: Linhas 015 e 017. Acompanhemos a execução do programa: após ser carregado na memória, ele inicia a sua execução na linha 014 do programa principal com o comando Num:=13. Vejamos a consequência disso a cada linha: 015: Será exibido Num Antes P1_Amarracao: 13; 016: Temos a chamada a rotina de nome P1_Amarracao; 006: Inicia-se sua execução, ou seja, Begin da rotina P1_amarracao; 007: Tot = 0; 008: Num = 2; 009: Tot = 0 + 2, em que tot = 2; 010: Será exibido Dentro de P1_Amarracao: Num: 2 Tot: 2 e �nalizará a execução da rotina; 017: Volta-se ao programa principal, que será exibido pelo comando Writeln: Num Pos P1_amarracao: 13. Repare ainda que, na linha 014, há uma amarração para atribuir um valor a Num (declarada globalmente no programa principal), que recebe o valor 13; já na 016, há uma nova amarração, dessa vez chamando P1_amarracao, que abrirá em um novo contexto: uma ativação de P1_amarracao. Comentário Ao sair desse contexto, a referência à variável Num local será perdida. Ao se retornar ao programa principal, volta a valer o valor global de Num: 13 (atribuído na linha 014). Atenção! Aqui existe uma videoaula, acesso pelo conteúdo online Atenção! Aqui existe uma videoaula, acesso pelo conteúdo online Escopo de visibilidade Uma amarração geralmente tem um escopo de visibilidade, que é a área do programa em que a entidade é visível, podendo ser referenciada. Um escopo de visibilidade pode ser estático ou dinâmico, tendo relação com o ambiente da amarração: Escopos de visibilidade Clique no botão acima. Escopo estático As entidades são amarradas em tempo de compilação do programa. A linguagem Algol 60 foi a primeira a introduzir o conceito de associação de identi�cadores a variáveis não locais, o que foi copiado pela maioria das LPs imperativas que a sucederam. A utilização do escopo estático nas linguagens se deve, em grande parte, às de�nições das unidades do programa (sub-rotinas). Em todas as linguagens de escopo estático, exceto em C, C++, Java e Fortran, as unidades, que são os subprogramas, podem ser aninhadas dentro de outras unidades, criando uma hierarquia de escopo. Para compreender o conceito e a aplicação do escopo estático, é necessário entendermos o conceito de bloco em uma LP. Em geral, um bloco, de�nido como um conjunto de instruções executados sequencialmente, pode ser: Um subprograma (procedimento e função); Um trecho de código delimitado por marcadores. São marcadores para blocos as seguintes LPs: Pascal, Algol e Ada: Usam os termos Begin e End para delimitar blocos; C, C++ e Java: usam as chaves {} para delimitaros blocos. Considere este trecho de código escrito na linguagem Pascal: Podemos observar nele dois blocos delimitados por Begin e End: Bloco 1: Programa principal; Bloco 2: Comando For. Observe agora o trecho de código abaixo: escrito em C, também há nele dois blocos delimitados por chaves { }: Program Exp_PASCAL; Var Tot, Num, I: integer; Begin Tot:=0; For I:-1 to 10 do Begin Readln (Num); Tot:=Tot+Num; End; End. main () { int i=0, x=100; while (i++ < 100) { float x = 3.231; printf {“x = %f/n”, x*i); } { Bloco 1: Programa principal aparece após o main (). As chaves estão nas linhas 02 e 08. Bloco 2: Do comando while. Chaves estão nas linhas 05 e 09. A imagem a seguir mostra que um bloco pode ser estruturado de três formas: a) Bloco monolítico Todo programa possui um bloco único. Todas as amarrações têm como escopo de visibilidade o programa todo. Trata-se de uma estrutura elementar e inadequada para grandes programas, que exigem modularização do código. Versões antigas de Basic e Cobol usaram essa estrutura, que hoje já está ultrapassada. b) Blocos não aninhados O programa pode ser dividido em blocos de subprogramas (y, z e w, por exemplo). O escopo de visibilidade das amarrações é o bloco cujos identi�cadores são declarados: Se criados dentro do bloco, são chamados de locais (ao bloco); Se criados fora do bloco, são globais. Todos os subprogramas são separados: cada um atua como um bloco. A LP Fortran adota essa estrutura. c) Blocos aninhados Trata-se da estrutura mais avançada. Qualquer bloco pode ser criado (aninhado) dentro de outro. A visibilidade é de dentro para fora: procura-se localmente (no bloco onde é usada) a amarração; caso ela não seja encontrada, deve-se procurar no bloco mais externo imediato – e assim por diante. Sua estrutura é adotada por linguagens como Pascal, Modula-2, Ada, C, C++ e Java. Entidades podem �car inacessíveis quando for usado o mesmo identi�cador para referenciar entidades diferentes em blocos aninhados, como é apontado no programa abaixo em C: Figura 1: Estrutura de blocos. (Fonte: Varejão, 2004) Bloco monolítico Blocos não aninhados Blocos aninhados main () { int i=0, x=10; while (i++ < 100) { float x = 3.231; printf {“x = %f/n”, x*i); } { Neste trecho de programa, a variável x, do tipo inteiro, criada no bloco mais externo (main), não é visível dentro do mais interno (while), em que x é uma variável do tipo �oat (números com casas decimais). Em qual bloco x é usado por inteiro no programa? Para evitar essa possível confusão no código, Java não permite que um mesmo identi�cador seja usado para referenciar entidades distintas em blocos aninhados. Observe agora a estrutura de blocos de uma linguagem no estilo Algol na imagem apresentada à esquerda. À direita, temos a representação desse ninho de blocos em uma estrutura de árvore: Analisando a imagem, constatamos que: As unidades B e E estão estaticamente envolvidas pela unidade A; F e G estaticamente pertencem à unidade E; C pertence a B; D pertence a C. Se, no exemplo acima, uma variável local fosse declarada na unidade B, então: Não é visível a A, E, F e G; É visível a B, C e D; É global a C e local a B. Da mesma forma, se uma variável de nome V fosse declarada tanto em A como em C, qualquer referência a V: Dentro de A, B, E, F e G se refere a V local a A; Dentro de C e D se refere a V local a C. Vamos analisar agora um trecho de programa na linguagem C que use uma abordagem mista cujos blocos de�nidos por funções adotam uma estrutura não aninhada e os blocos internos, uma estrutura aninhada: Figura 2: Estrutura de blocos no estilo Algol. O programa principal (main) tem acesso: Aos procedimentos F () e G (); Às variáveis globais X e Y, ambas inteiras (declaradas nas linhas 01 e 02) no código. Já os procedimentos F () e G () têm acesso: Às variáveis globais X e Y; Às respectivas variáveis locais: em F (), a variável Z; em G (), a variável W. Pela regra de escopo da linguagem de programação C, a função G () tem acesso ao procedimento função F () porque foi declarada antes da função G. Vamos avaliar mais um programa para compreender o escopo estático. Considere o exemplo a seguir na linguagem Pascal: Int x=10; Int y=15; Void F () { If (y-x) { int z=x+y; } } Void G () { int w; w=x; } main ( ) { F (); X=x+3; G (); } O comando de atribuição, dentro de Sub1, acessa a variável global declarada no programa principal BIG. No escopo estático, a procura por X começa no procedimento que lhe faz referência (no caso, Sub2), que não tem declaração local. A procura segue pelo chamado pai estático de Sub1, que é o programa principal BIG. Por isso, a referência a X em Sub1 é feita pela variável declarada globalmente. Escopo dinâmico As amarrações ocorrem conforme o �uxo de controle do programa e à medida que as rotinas vão sendo chamadas, ou seja, em tempo de execução. Baseia-se, portanto, na sequência de chamadas das unidades (subprogramas) do programa principal. As primeiras linguagens a implementarem o escopo dinâmico foram APL, SNOBOL4 e Lisp. Ao mesmo trecho de código escrito em Pascal no item anterior, adicionaremos chamadas às unidades Sub2 e Sub1 para podermos entender como funciona o escopo dinâmico: Procedure BIG; Var X: integer; Procedure Sub1; Begin X:=1; end; Procedure Sub2; Var X: integer; Begin Sub1; end; Begin {BIG} Sub2; End. Procedure BIG; Var X: integer; Procedure Sub1; Begin X:=12; end; Procedure Sub2; Var X: integer; Begin Sub1; end; Begin {BIG} Sub2; End. O signi�cado do identi�cador X referenciado em Sub1, por se tratar de um escopo dinâmico, não pode ser determinado pelo tempo de compilação, mas apenas durante a execução. No escopo dinâmico, pode-se referenciar a variável a partir de qualquer declaração de X. Há dependência da sequência da chamada à unidade até que uma declaração de X seja localizada. Se nenhuma for encontrada, haverá um erro na execução do programa. Assim como ocorre no escopo estático, a procura, agora durante a execução, começa pelas declarações locais; depois, procura-se no pai dinâmico ou procedimento de chamada. Vamos analisar as chamadas referenciadas no código acima: Sub2 é chamada pelo programa principal BIG; Na execução de Sub2, a unidade Sub1 é acionada; Sub1 faz referência ao identi�cador X. Como foi Sub2 que chamou Sub1 e há uma declaração de X em Sub2, logo Sub1 vai referenciar o X declarado em Sub2. Suponha agora que o Sub1 seja chamado diretamente de BIG conforme trecho de código abaixo: O pai dinâmico de Sub1 é BIG. Já a referência a X passa a ser a que foi declarada em BIG. A maioria das LPs, hoje em dia, não adota o escopo dinâmico em função dos seguintes problemas colaterais: Perda de e�ciência, já que a veri�cação de tipos se dá em tempo de execução; Redução na legibilidade, pois a sequência dos subprogramas deve ser conhecida; Redução na con�abilidade, porque as variáveis locais podem ser referenciadas por qualquer subprograma subsequente; Acesso ine�ciente às variáveis, pois ele precisa seguir a sequência de chamadas aos subprogramas para identi�car as referências que não forem locais. A maioria das linguagens irá implementar o escopo estático, pois, com ele, os programas, em comparação àqueles escritos em LPs com escopo dinâmico, �carão: Mais legíveis; Mais con�áveis; Com execução mais rápida. Begin {BIG} Sub1; End. Atividade 1. Sobre o conceito dos identi�cadores e como as LPs os implementam, avalie: I. Um identi�cador faz referência, entre outras coisas, a uma variável ou a um nome de uma unidade (subprograma). II. As LPs que implementarem a propriedade case sensitive em identi�cadores tendem a apresentar problema de legibilidade e entendimento do código. III. O nome do identi�cador deve ser autoexplicativo. IV. Os identi�cadores especiais são elementos da linguagem que podem ou não ser rede�nidos pelos programadores como palavras reservadas. Com base em sua análise, marquea opção que apresenta apenas as assertivas corretas. a) I, III e IV b) I e IV c) I d) II e IV e) II e IV 2. Associe as duas colunas. Na coluna à esquerda, temos os tipos de amarração; na coluna à direita, os tempos de amarração. Associe o tipo de amarração (coluna 1) ao seu respectivo tempo de amarração (coluna 2). Cada tipo de amarração pode estar associado a um tempo de amarração. Mas pode ser que o tempo de amarração não tenha associação ou que tenha mais de uma associação. Associe o número (1 a 5) da coluna “tipo de amarração” com a letra (A a E) de “tempo de amarração”. Tipo de amarração 1. Identi�cador ao seu tipo de dado 2. Identi�cador a uma posição memória 3. Identi�cador a uma unidade (subprograma) 4. Identi�cador de variável global 5. Atribuição de valor a uma variável Tempo de amarração a. Em tempo de execução b. Em tempo de compilação c. Em tempo de ligação d. Em tempo de projeto da LP e. Em tempo de carga do programa 3. Em uma LP que implemente o escopo estático para as amarrações, avalie as assertivas e a relação de causa e efeito entre elas. I. Na LP XPTO, que implementa o escopo estático de visibilidade, o primeiro local onde busca-se a declaração de determinada variável é na unidade corrente. Em seguida, procura-se na unidade mais externa imediata. II. A visibilidade, em escopo estático, é de dentro para fora. Com base em sua análise, assinale a única alternativa correta: a) As duas assertivas são verdadeiras, e a segunda justifica a primeira. b) As duas assertivas são verdadeiras, e a segunda não justifica a primeira. c) As duas assertivas são falsas. d) A assertiva I é verdadeira; a II, falsa. e) A assertiva II é verdadeira; a I, falsa. Notas Referências GHEZZI, C.; JAZEYERI, M. Conceitos de linguagens de programação. 2. ed. Rio de Janeiro: Campus, 1987. SEBESTA, R. W. Conceitos de linguagem de programação. 9. ed. Porto Alegre: Bookman, 2011. VAREJÃO, F. M. Linguagem de programação: conceitos e técnicas. Rio de Janeiro: Elsevier, 2004. Próxima aula De�nições e declarações: amarrações; Os tipos de dados de uma LP. Explore mais Do C/C++ para o Java: Conheça as diferenças e principais características; Análise quantitativa e comparativa de linguagens de programação. javascript:void(0); javascript:void(0);
Compartilhar