Fundamentos da Programação 32 VIII. VARI ÁVEIS A. Conceito Variáveis contém dados: • de entrada que o computador precisa manipular; • de saı́da que o computador precisa imprimir; e • temporários, utilizados de modo auxiliar o cálculo ou processamento. As variáveis pode ser: • Numéricas: contém números inteiros ou reais, que são expressos pelos dı́gitos “0” a “9”, pelos sinais “+” e “−” e pelo ponto decimal “.”. • Alfanuméricos: podem ser formados por qualquer caracter presente na tabela ASCII ou nas tabelas dela derivadas (detalhes adiante). • Lógicas: podem assumir apenas dois valores: TRUE para valores verdadeiros e FALSE para falsos. • Ponteiros: podem armazenar apenas endereços de memória. B. Arquitetura da Memória A memória em um computador corresponde a um espaço utilizado para armazenamento de informação em caráter permanente (não-volátil) ou temporário (volátil). Cada posição de memória consiste de (veja Tab. I): • endereço: especifica em que posição a célula de memória encontra-se; e • conteúdo: informação armazenada. Conteúdo pode ser limitado a 1 byte ( = 8 bits) ou a múltiplos bytes (em geral 2 e 4 bytes). Cada byte permite representar 28 = 256 valores diferentes. Tabela I A RQUITETURA DA MEM ÓRIA Endereço 0x0000 0x0001 0x0002 ... 0xFFFF Conteúdo 0x34 0xB0 0x23 ... 0x00 C. Armazenamento de Dados Cada tipo de dado (inteiro, real, alfanumérico, lógico ou ponteiro) necessita de uma certa quantidade de memória para ser armazenado. Esta quantidade depende do tipo de dado, do tipo de computador e do tipo da linguagem. 1) Armazenamento de Dados do Tipo Numérico Inteiro: Suponha que a variável pertença ao conjunto de números naturais (N), isto é, possui apenas valores positivos. Apenas um subconjunto de N pode ser armazenado, sendo o tamanho desse subconjunto determinado pela quantidade de bytes disponı́veis para a armazenagem, como colocado abaixo. • Armazenamento utilizando 1 byte por variável: os valores que a variável pode assumir são: 0, 1, . . . , 255 = 28 − 1. • Armazenamento utilizando 2 bytes por variável: os valores que a variável pode assumir são: 0, 1, . . . , 65.535 = 216 − 1. • Armazenamento utilizando 4 bytes por variável: os valores que a variável pode assumir são: 0, 1, . . . , 4.294.967.295 = 232 − 1. Suponha que a variável pertença ao conjunto de números inteiros (Z), isto é, possui valores positivos e negativos. Apenas um subconjunto de Z pode ser armazenado, sendo o tamanho desse subconjunto determinado pela quantidade de bytes disponı́veis para a armazenagem, como colocado abaixo. UEM/CTC/DIN/Elvio Fundamentos da Programação 33 Armazenamento utilizando 1 byte por variável: os valores que a variável pode assumir utilizando complemento de 2 são: −128 = −27 , . . . , −1, 0, 1, . . . , 127 = 27 − 1. • Armazenamento utilizando 2 bytes por variável: os valores que a variável pode assumir utilizando complemento de 2 são: −32.768 = −215 , . . . , 32.767 = 215 − 1. • Armazenamento utilizando 4 bytes por variável: os valores que a variável pode assumir utilizando complemento de 2 são: −2.147.483.648 = −231 , . . . , 2.147.483.647 = 231 − 1. Portanto, o espaço necessário para armazenar um dado do tipo inteiro depende dos valores esperados para esse dado. Algumas linguagens permitem a diferenciação entre os diversos tamanhos, por exemplo: • short integer integer long integer → → → utiliza 1 byte utiliza 2 bytes utiliza 4 bytes Outras linguagens não fazem esta distinção e utilizam sempre o maior tamanho disponı́vel. 2) Armazenamento de Dados do Tipo Numérico Fracionário: A variável pertence ao conjunto de números reais (R), isto é, possui uma parte inteira e uma parte fracionária. Apenas um subconjunto de R pode ser armazenado, sendo o tamanho desse subconjunto determinado pela quantidade de bytes disponı́veis para a armazenagem. Algumas linguagens permitem a diferenciação entre os diversos tamanhos, por exemplo: float double → → utiliza 2 bytes utiliza 4 bytes Outras linguagens não fazem esta distinção e utilizam sempre o maior tamanho disponı́vel. 3) Armazenamento de Dados do Tipo Alfanumérico: O conjunto de caracteres (letras, dı́gitos e sı́mbolos especiais) diferentes utilizados nas linguas européias é menor que 256. Assim apenas 1 byte é suficiente para representar todos os valores alfanuméricos. Cada letra, dı́gito ou sı́mbolo especial é representado por um número entre 0 e 255. A primeira tabela de conversão caracter ↔ número foi padronizada no começo dos anos 60 para a comunicação entre computadores. Esta tabela foi denominada ASCII (American Standard Code for Information Interchange), e utiliza os valores apenas entre 0 e 127, sendo que ela inclui apenas as letras encontradas na lingua inglesa (veja Tab. II). O padrão ASCII extendido utiliza os valores entre 0 e 255 e inclui caracteres especiais encontrados em outras linguas européias (letras acentuadas, etc.). Atualmente a conversão caracter ↔ número deve utilizar o padrão internacional ISO 8859-15. Exemplo: Armazenamento da palavra banana a partir do endereço 0x1000 pode ser feito como colocado na Tab. III. O comprimento da palavra banana é de 6 caracteres e o espaço necessário para armazenar a palavra é de 6 bytes contı́guos. Um byte extra pode ser utilizado para armazenar o comprimento da variável alfanumérica. Para o exemplo acima, o armazenamento de banana pode ser feito conforme mostrado na Tab. IV. Uma outra alternativa é colocar um byte ao final da cadeia de caracteres alfanuméricos. O caracter NULL foi colocado no exemplo da Tab. V para indicar o final da palavra banana. 4) Armazenamento de Dados do Tipo Lógico: Este tipo possui apenas 2 valores possı́veis: TRUE e FALSE. Assim apenas 1 bit seria suficiente para armazenar a informação deste tipo de variável. Entretanto a menor porção de memória que se pode acessar é 1 byte e, desta maneira, a informação do tipo lógico é armazenada em 1 byte. Este fato representa um desperdı́cio mas simplifica bastante a arquitetura da memória do computador e, ao final, acaba sendo vantajoso. De maneira similar ao dado do tipo literal, a cada um dos valores TRUE e FALSE deve ser atribuido um valor numérico. Possivelmente a conversão mais utilizada neste caso é a que aparece na Tab. VI. D. Exemplos 1) Pascal: A linguagem Pascal apresenta os seguintes tipos de variáveis: UEM/CTC/DIN/Elvio Fundamentos da Programação 34 Tabela II TABELA ASCII Valor Caracter Valor Caracter Valor 000 0x00 NUL∗ 032 0x20 Space 064 0x40 001 0x01 SOH∗ 033 0x21 ! 065 0x41 002 0x02 STX∗ 034 0x22 ” 066 0x42 003 0x03 ETX∗ 035 0x23 # 067 0x43 004 0x04 EOT∗ 036 0x24 $ 068 0x44 005 0x05 ENQ∗ 037 0x25 % 069 0x45 006 0x06 ACK∗ 038 0x26 & 070 0x46 007 0x07 BEL∗ 039 0x27 ’ 071 0x47 008 0x08 BS∗ 040 0x28 ( 072 0x48 009 0x09 HT∗ 041 0x29 ) 073 0x49 010 0x0A LF∗ 042 0x2A * 074 0x4A 011 0x0B VT∗ 043 0x2B + 075 0x4B 012 0x0C FF∗ 044 0x2C , 076 0x4C 013 0x0D CR∗ 045 0x2D 077 0x4D 014 0x0E SO∗ 046 0x2E . 078 0x4E 015 0x0F SI∗ 047 0x2F / 079 0x4F 016 0x10 DLE∗ 048 0x30 0 080 0x50 017 0x11 DC1∗ 049 0x31 1 081 0x51 018 0x12 DC2∗ 050 0x32 2 082 0x52 019 0x13 DC3∗ 051 0x33 3 083 0x53 020 0x14 DC4∗ 052 0x34 4 084 0x54 021 0x15 NAK∗ 053 0x35 5 085 0x55 022 0x16 SYN∗ 054 0x36 6 086 0x56 023 0x17 ETB∗ 055 0x37 7 087 0x57 024 0x18 CAN∗ 056 0x38 8 088 0x58 025 0x19 EM∗ 057 0x39 9 089 0x59 026 0x1A SUB∗ 058 0x3A : 090 0x5A 027 0x1B ESC∗ 059 0x3B ; 091 0x5B 028 0x1C FS∗ 060 0x3C < 092 0x5C 029 0x1D GS∗ 061 0x3D = 093 0x5D 030 0x1E RS∗ 062 0x3E > 094 0x5E 031 0x1F US∗ 063 0x3F ? 095 0x5F ∗ representa caracteres especiais, que não são impressos Caracter @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ˆ Valor 096 0x60 097 0x61 098 0x62 099 0x63 100 0x64 101 0x65 102 0x66 103 0x67 104 0x68 105 0x69 106 0x6A 107 0x6B 108 0x6C 109 0x6D 110 0x6E 111 0x6F 112 0x70 113 0x71 114 0x72 115 0x73 116 0x74 117 0x75 118 0x76 119 0x77 120 0x78 121 0x79 122 0x7A 123 0x7B 124 0x7C 125 0x7D 126 0x7E 127 0x7F Caracter ‘ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ˜ DEL Tabela III Endereço 0x1000 0x1001 0x1002 0x1003 0x1004 0x1005 • 0x62 0x61 0x6E 0x61 0x6E 0x61 Conteúdo = 98 = 97 = 110 = 97 = 110 = 97 = = = = = = b a n a n a BOOLEAN: Tipo lógico que pode assumir apenas os valores TRUE e FALSE, e ocupa 1 byte de memória. CHAR: Tipo alfanumérico que pode ter como conteúdo um caracter, e ocupa 1 byte de memória. • STRING: tipo alfanumérico que pode ter como conteúdo uma cadeia de caracteres. O número • • • • • de bytes que ocupa na memória pode variar de 2 a 256 bytes, dependendo do comprimento da cadeia de caracteres. O primeiro byte contém a quantidade efetiva de caracteres da cadeia. BYTE: Tipo numérico inteiro positivo que pode assumir os valores de 0 a 255, e ocupa 1 byte de memória. WORD: Tipo numérico inteiro positivo que pode assumir os valores de 0 a 65.535, e ocupa 2 bytes de memória. INTEGER: Tipo numérico inteiro que ocupa usualmente 2 bytes na memória. LONGINT: Tipo numérico inteiro que ocupa usualmente 4 bytes na memória. UEM/CTC/DIN/Elvio Fundamentos da Programação 35 Tabela IV Endereço 0x1000 0x1001 0x1002 0x1003 0x1004 0x1005 0x1006 0x06 0x62 0x61 0x6E 0x61 0x6E 0x61 = = = = = = = Conteúdo 6 = comprimento 98 = b 97 = a 110 = n 97 = a 110 = n 97 = a Tabela V Endereço 0x1000 0x1001 0x1002 0x1003 0x1004 0x1005 0x1006 • 0x62 0x61 0x6E 0x61 0x6E 0x61 0x00 = = = = = = = Conteúdo 98 = 97 = 110 = 97 = 110 = 97 = 0 = b a n a n a NULL REAL: Tipo numérico real que ocupa usualmente 4 bytes na memória. 2) Fortran77: A linguagem Fortran77 apresenta os seguintes tipos de variáveis: • LOGICAL: Tipo lógico que pode assumir apenas os valores TRUE e FALSE, e ocupa 1 byte de memória. • CHARACTER: Tipo alfanumérico que pode ter como conteúdo uma cadeia de caracteres. O número de bytes que ocupa na memória pode variar de 2 a 256 bytes, dependendo do comprimento da cadeia de caracteres. O primeiro byte contém a quantidade efetiva de caracteres da cadeia. • INTEGER: Tipo numérico inteiro que ocupa usualmente 4 bytes na memória. • REAL: Tipo numérico real que ocupa usualmente 4 bytes na memória. • DOUBLE PRECISION: Tipo numérico real que ocupa usualmente 8 bytes na memória. • COMPLEX: Tipo numérico complexo que é armazenado como um conjunto ordenado de 2 variáveis do tipo REAL. 3) C: A linguagem C apresenta os seguintes tipos de variáveis: • char: Tipo alfanumérico que pode ter como conteúdo um caracter, e ocupa 1 byte de memória. • short int: Tipo numérico inteiro que ocupa usualmente 1 byte na memória. • int: Tipo numérico inteiro que ocupa usualmente 2 bytes na memória. • long int: Tipo numérico inteiro que ocupa usualmente 4 bytes na memória. • float: Tipo numérico real que ocupa usualmente 4 bytes na memória. • double: Tipo numérico real que ocupa usualmente 8 bytes na memória. • long double: Tipo numérico real que ocupa usualmente 12 bytes na memória. Os tipos numéricos podem ser qualificados pelos modificadores signed e unsigned para indicar um número com ou sem sinal, respectivamente. E. Conceito e Utilidade de Variáveis Para acessar uma informação diretamente na memória é necessário saber onde ela está (posição na memória), o tipo de variável e seu tamanho (número de bytes ocupados). Com o conceito de variável, para o usuário acessar a informação armazenada por uma variável basta saber o nome e o tipo da variável. Onde está e o tamanho utilizado para o armazenamento são detalhes com os quais o programador não precisa preocupar-se. Uma variável possui três atributos: nome, tipo de dado e informação armazenada. • Nome: tem a função de diferenciar a variável das demais; por esta razão os nomes devem ser únicos. UEM/CTC/DIN/Elvio Fundamentos da Programação 36 Tabela VI Valor Lógico FALSE TRUE Valor Numérico 0 qualquer outro valor Tipo de Dado: refere-se ao tipo de informação a ser armazenada. Informação: conteúdo da memória. Em geral nomes de variáveis devem começar com uma letra e não podem conter nenhum caracter especial, exceto o underscore ( )1 . Exemplos: • • salario salário 1ano ano1 a casa sal/hora sal_hora _desconto → → → → → → → → correto incorreto, incorreto, correto incorreto, incorreto, correto incorreto, contém o caracter á não começa com uma letra contém o caracter espaço contém o caracter / não começa com uma letra Obviamente o nome da variável deve ser tal que a sua função no algoritmo fique mais clara. O nome e o tipo de dado não podem ser alterados durante a execução do algoritmo. Por outro lado, o atributo informação é alterado de acordo com as necessidades do algoritmo. F. Declaração Todas as variáveis devem, de modo geral, ser declaradas antes de serem utilizadas. O nome de uma variável deve ser único em cada bloco, sendo que apenas os primeiros n caracteres do nome são significativos (o valor de n depende da linguagem e do sistema). Para Fortran77 a sintaxe de declaração é tipo nome [, nome [, nome . . . ]] onde nome e tipo são, respectivamente, o nome e o tipo da variável. Em Fortran77 a primeira letra do nome da variável pode ser utilizado para determinar o tipo da variável quando não houver uma declaração explicita. A regra geral é que letra inicial I-N letra inicial A-H ou O-Z → → tipo INTEGER tipo REAL Exemplos (para Fortran77): CHARACTER*10 nome INTEGER*1 idade REAL salario REAL min, max LOGICAL tem_filhos CHARACTER resp Variáveis de mesmo tipo podem ser definidas na mesma linha, separando os seus nomes por virgulas (veja acima as variáveis min, max). Embora não seja padrão no Fortran77, muitos compiladores para essa linguagem permitem que o programador especifique o número de bytes utilizado para armazenar a variável. Nos exemplos acima, a variável idade é declarada para armazenar 1 byte. Outros exemplos: LOGICAL*1, INTEGER*2, REAL*8, COMPLEX*16, referem-se, respectivamente, a uma variável lógica com 1 byte, inteira com 2 bytes, real com 8 bytes e complexa com 16 bytes. 1 Fortran77 não permite a utilização do underscore; entretanto muitos compiladores para Fortran77, incluindo o Force-2.0, permitem que esse caracter seja utilizado. UEM/CTC/DIN/Elvio Fundamentos da Programação 37 Tabela VII E XEMPLO DE MAPEAMENTO DE VARI ÁVEIS NA MEM ÓRIA Nome Simbólico nome idade salario min max tem_filhos resp Posição Inicial 0x2000 0x200A 0x200C 0x2012 0x2018 0x201E 0x201F Tipo de Dado CHARACTER*10 (10 bytes) INTEGER*1 (1 byte) REAL (6 bytes) REAL (6 bytes) REAL (6 bytes) LOGICAL (1 byte) CHARACTER (1 byte) G. Atribuição No Fortran77 a atribuição de valores às variáveis é feita pelo operador =. Exemplos: INTEGER indice CHARACTER resp REAL valor CHARACTER*20 palav LOGICAL s_n INTEGER dia, mes, ano INTEGER quant indice = 1 resp = ’S’ palav = ’Palavra’ valor = 178.987 s_n = .TRUE. quant = -56 dia = 9 mes = 10 ano = 1989 H. Exemplo de Mapeamento de Variáveis na Memória O computador não trabalha com nomes simbólicos, como aqueles definidos para as variáveis. Para o computador, a memória somente pode ser acessada através de endereços. Portanto, alguém precisa relacionar nomes simbólicos com endereços na memória. Este trabalho é executado pelo compilador ou interpretador, que monta uma tabela de sı́mbolos, como a que está colocada na Tab. VII. UEM/CTC/DIN/Elvio