Laboratório de Programação
Prof. Oscar Luiz Monteiro de Farias
[email protected]
Capítulo 2
Tipos,
Operadores
e
Expressões
Variáveis, operadores e exps




Variáveis e constantes são os objetos de dados básicos
manipulados por um programa em C.
As declarações listam as variáveis a serem usadas,
definem os tipos assumidos pelas mesmas e
eventualmente estabelecem os seus valores iniciais.
Os operadores especificam as operações que devem ser
realizadas com as variáveis.
As expressões combinam variáveis e constantes, por
meio dos operadores, a fim de produzir novos valores
(que são eventualmente armazenados em variáveis).
Identificadores (1)




Os nomes de variáveis e constantes simbólicas
são compostos por letras e dígitos; o primeiro
caracter deve ser uma letra.
Não inicie identificadores com um '_', pois as
funções da biblioteca padrão normalmente usam
nomes assim.
Maiúsculas e minúsculas são distintas (x e X
representam nomes distintos)
Use minúsculas para as variáveis e maiúsculas
para as constantes simbólicas (convenção do C).
Identificadores (2)




Pelo menos os 31 primeiros caracteres de um
nome interno são significativos.
Para os nomes externos o padrão ANSI garante
que apenas os 6 primeiros caracteres são
significativos, bem como um único tipo de letra
(m ou M).
As keywords (if, else, int, for, float, etc.) não
podem ser usadas como nomes de variável.
As keywords devem ser escritas em
minúsculas.
Tipos de dados básicos (1)
char - um único byte - capaz de representar um
caracter no conjunto de caracteres local

int - inteiro, reflete o tamanho dos inteiros no hardware
da máquina → usualmente 16bits (-32768 <= valor <=
32767) ou 32 bits

float – ponto flutuante em precisão simples
usualmente 32 bits - com pelo menos 6 dígitos
significativos 10-38 <=valor<=10+38

double - ponto flutuante com precisão dupla

Os tamanhos dos objetos em ponto flutuante são
definidos pela implementação

Tipos de dados básicos (2)

Há qualificadores que podem ser aplicados aos tipos básicos
long double - ponto flutuante com precisão estendida.
short int - inteiro curto, normalmente ocupa16 bits
long int - inteiro longo, normalmente ocupa 32 bits
Ex.: short int counter;



Cada compilador é livre para escolher os tamanhos adequados
ao seu hw;
Restrições: i) short e int devem ocupar pelo menos 16 bits;
ii) short <=int <= long
Os qualificadores signed ou unsigned podem ser aplicados a
char ou a qualquer inteiro.
Tipos de dados básicos (3)


Números unsigned são sempre positivos ou zero.
Obedecem as leis da aritmética módulo 2n, onde n é o número de
bits do tipo correspondente.
ex.: unsigned char x; → 0 <= x <= 255
signed char x; → -128 <= x <= 127
(em máquinas que usam o complemento a dois)

Os arquivos headers standard <limits.h> e <float.h> contêm
constantes simbólicas para todos os tamanhos, juntamente com
soutra propriedades da máquina e do compilador.

Os arquivos headers do C estão localizados em /usr/include.

Ver o apêndice B do livro K&R.
Constantes (1)






Constante inteira → 1234
Constante long → 123456789L
Um inteiro muito grande para caber em um int
será considerado como long.
Constantes não sinalizadas são escritas com a
letra u ou U ao final
O sufixo ul ou UL indica unsigned long
Constantes de ponto flutuante contêm um ponto
decimal → 123.4 ou um expoente → 1e-2
Constantes (2)

Seu tipo é double, a menos que tenham um sufixo.

F ou f → indicam uma constante float

L ou l → constante long double




O valor de um inteiro pode ser especificado em decimal,
octal ou hexadecimal
Um zero inicial em uma constante inteira significa octal →
037 (octal) = 31 em decimal
0X ou 0x inicial significam um número hexadecimal → 0x1f
ou 0X1F = 31 em decimal
Constantes octais ou decimais podem ser seguidas por l ou L
(para torná-las long) ou por u ou U (para torná-las unsigned).
Constantes (3)






Uma constante de caracter é um inteiro, escrito como um
caracter entre aspas → 'x'
O valor de uma constante de caracter é o valor numérico do
caracter no conjunto de caracteres da máquina
Ex.: a constante de caracter '0' tem o valor 48 no conjunto
de caracteres ASCII, que não está relacionado ao valor
numérico 0.
Escrevendo '0' no lugar do valor numérico 48 o programa
se torna independente do valor e mais fácil de ser lido.
Constantes de caracteres participam em operações
aritméticas como quaisquer outros inteiros
Seqüência de escape → \n - \t - \b (um único caracter)
Constantes (4)
Um padrão de bits arbitrário, do tamanho de
um byte, pode ser especificado por '\000', onde
00 é de um a dois dígitos octais (0..7).

ou por '\xhh`, onde hh é de um a dois dígitos
hexadecimais (0...9, A...F).
#define VTAB '\013' /* ASCII vertical tab */
#define BELL '\007' /* ASCII bell character */
#define VTAB '\xb'
/* ASCII vertical tab */
#define BELL '\x7'
/* ASCII bell character */

Seqüências de escape
\a
alert (bell)
\\
backslash
\b
backspace
\?
question mark
\f
formfeed
\'
single quote
\n
newline
\"
double quote
\r
carriage return
\ooo
octal number
\t
horizontal tab
\xhh
hexadecimal number
\v
vertical tab
Constantes (5)




Uma expressão constante é uma expressão que
envolve apenas constantes
É avaliada em tempo de compilação
Podem ser usadas como constantes também
Exemplos:
#define MAXLINE 1000
char line[MAXLINE+1];
#define LEAP 1 /* in leap years */
int days[31+28+LEAP+31+30+31+30+31+31+30+31+30+31];
Constantes (6)
Uma constante do tipo cadeia (string) ou literal
do tipo cadeia é uma seqüência de zero ou mais
caracteres delimitados por aspas
''Eu sou uma cadeia de caracteres''
'''' /* cadeia vazia ou nula */

As mesmas seqüências de escape ssão usadas
nas cadeias

Constantes do tipo cadeia podem ser
concatenadas em tempo de compilação
''Rio'' ''de'' ''Janeiro'' == ''Rio de Janeiro''

Constantes (7)






Uma cadeia é um vetor cujos elementos são caracteres.
A representação interna de uma cadeia possui um
caracter nulo '\0' ao seu final.
A área física de armazenamento é sempre um a mais do
que o número de caracteres entre aspas.
A função da biblioteca padrão strlen (s) retorna o
tamanho da cadeia s, excluindo o '\0' final.
Ver prog17-chap02-pg38.c
O arquivo <string.h> possui declarações de várias
funções de cadeias
Constantes (8)



'x' não é o mesmo que ''x''
'x' é uma constante de caracter, um inteiro usado
para produzir o valor numérico da letra x no
conjunto de caracteres da máquina.
''x'' é uma cadeia de caracteres (ou vetor) que
contém o caracter x e um '\0'.
Constante de enumeração (1)
É uma lista de valores inteiros constantes
enum boolean { NO, YES };
o primeiro nome em uma enum tem o valor 0, o
seguinte 1, e assim por diante, a não ser que valores
explícitos sejam especificados.

Se nem todos os valores foram especificados, aqueles
que não o foram continuama progressão a partir do
último valor informado
enum months { JAN = 1, FEB, MAR, APR, MAY, JUN,
JUL, AUG, SEP, OCT, NOV, DEC };
/* FEB = 2, MAR = 3, etc. */

Constante de enumeração (2)



Os nomes em diferentes enumerações devem
ser distintos.
As enumerações fornecem uma forma
conveniente de associar valores constantes a
nomes.
É uma alternativa ao uso de #define, com a
vantagem dos valores serem gerados pelo
compilador.
Declarações (1)



Todas as variáveis devem ser declaradas antes
de serem usadas
Certas declarações podem ser feitas
implicitamente pelo contexto (eg. variáveis
extern).
Uma declaração especifica um tipo e é seguida
por uma ou mais variáveis daquele tipo
int lower, upper, step;
char c, line[1000];
Declarações (2)
Pode-se inicializar uma variável em sua
declaração
char esc = '\\';
int i =0;
float eps = 1.0e-5;

Se a variável não for automática (local à função)
a inicialização é feita uma única vez, antes do
início do programa e o inicializador deve ser
uma expressão constante.

Declarações (3)



Uma variável automática explicitamente
inicializada tem seu valor inicializado toda vez
que a função ou bloco em que se encontra
ganhar o controle do programa.
Por default as variáveis externas e estáticas
são inicializadas com zero.
Variáveis automáticas sem inicializações
explícitas assumem valores iniciais indefinidos
(lixo).
Declarações (4)
O qualificador const pode ser aplicado à
declaração de qualquer variável, indicando que
a mesma não poderá ser alterada.
const double e = 2.71828182845905;
const char msg[] = "warning: ";

const pode ser aplicado a argumentos do tipo
vetor, indicando que os seus elementos não
podem ser alterados
int strlen(const char[]);

Operadores aritméticos





+, -, *, /, % (módulo)
A divisão inteira trunca a parte fracionária
x % y é igual a zero se x for um múltiplo de y;
em caso contrário é o resto da divisão de x por y
+ e – possuem a mesma precedência que é
menor que a dos operadores *, / e %, que por
sua vez é menor que a dos operadores unários +
e -.
Os operadores aritméticos se associam da
esquerda para a direita.
Operadores relacionais e lógicos (1)
Relacionais: >, >= , < , <= possuem a mesma
precedência.

De igualdade: == , != têm maior precedência
que os operadores relacionais.

Os operadores relacionais possuem menor
precedência que os aritméticos.
Expressões como i < lim -1 são avaliadas como
i < (lim -1)

Lógicos: &&, ||

Operadores relacionais e lógicos (2)


Expressões conectadas por && e || são avaliadas da
esquerda para a direita, e a avaliação pára, assim que a
veracidade ou falsidade do resultado for conhecida.
A maioria dos programas em C fundamenta-se nessas
propriedades.
for (i=0; i < lim-1 && (c = getchar()) != '\n' && c != EOF; ++i)
s[i] = c;


A precedência de && é maior que a de || e ambos têm
menor precedência que os operadores relacionais e de
igualdade.
A precedência de != é maior que a da atribuição =
Operadores relacionais e lógicos (3)
Por definição, o valor numérico de uma
expressão relacional ou lógica é 1 se a relação
for verdadeira e 0 se a relação for falsa.

O operador unário de negação ! converte um
operando diferente de 0, ou verdadeiro, no valor
0, e um operador 0 ou falso no valor 1.

if (!valid)
/* ao invés de */
if (valid == 0)

Conversões de tipo (1)


Operador com operandos de
diferentes tipos → conversão dos
operandos para um tipo comum,
segundo regras.
Em geral, as conversões automáticas
são aquelas que convertem um
operando mais particular/estreito para
um mais geral/largo, sem perder
Conversões de tipo (2)




Um char é apenas um pequeno inteiro, de
modo que podem ser usados em expressões
aritméticas.
Esta propriedade fornece grande flexibilidade
em certos tipos de transformações de caracteres.
Ver prog18-chap02-pg40.c - função atoi
s[i] – '0' fornece o valor numérico do caracter
armazenado em s[i], pois os valores de '0', '1' …
'9' formam uma seqüência continuamente
crescente (vide ASCII table).
Conversões de tipo (3)
O arquivo header padrão <ctype.h> descrito no
apêndice B do livro do K&R
(/usr/include/ctype.h) fornece funções para teste
e conversão de caracteres, independente do
conjunto de caracteres usado.
tolower(c) / isdigit(c)

C não especifica se as variáveis do tipo char
são quantidades signed ou unsigned.

Dependendo do hardware a conversão de um
char para int pode produzir um inteiro negativo

Conversões de tipo (4)



Em algumas máquinas um char, cujo bit mais à
esquerda é 1 será convertido para um inteiro
negativo (''sign extension'').
Em outras, um char é promovido a um int,
incluindo-se 0 nos bits mais à esquerda, e é
sempre positivo.
A definição de C garante que qualquer caracter
pertencente ao conjunto de caracteres da
máquina jamais será negativo.
Conversões de tipo (5)
Lembrar que o valor de uma expressão
relacional ou lógica é 1 (verdadeiro) ou 0 (falso).

d = c >= '0' && c <= '9'
atribui 1 a d, se c for um dígito, e 0 se não for.

Todavia, funções como isdigit (c) podem
retornar qualquer valor não-zero, indicando um
resultado verdadeiro.

Na parte de teste de if, while, for, etc.,
verdadeiro significa não-zero.

Conversões de tipo – regras (1)
Ver apêndice A, seção 6, do livro do K&R.

Se não houver operandos do tipo unsigned, o
seguinte conjunto informal de regras basta:
a) If either operand is long double, convert the
other to long double.
b) Otherwise, if either operand is double, convert
the other to double.
c) Otherwise, if either operand is float, convert
the other to float.

Conversões de tipo – regras (2)
Em geral as funções matemáticas, como as de
<math.h> usam precisão dupla.

As regras de conversão são mais complicadas
quando operandos unsigned estão envolvidos.

A comparação entre valores signed e unsigned
são dependentes da máquina, pois dependem do
tamanho (# de bits) assumidos pelos inteiros.

Supor int (16 bits) e long (32 bits) →
-1L < 1U, porque 1U, unsigned int, é promovido
a

Conversões de tipo – regras (3)
int i;
char c;
...
i = c;
c = i;
O valor de c é inalterado. Isto é verdade
independente de se ter ou não extensão de sinal
envolvida. Todavia, invertendo-se a ordem dos
comandos de atribuição poderá levar à perda de
Conversões de tipo – regras (4)
Como os argumentos de uma função são
expressões, ocorrerá uma conversão de tipos
quando eles forem passados para a função
(atribuídos aos parâmetros).

usar um protótipo de função para forçar a
coerção de tipos (será visto + adiante)

Typecast – a conversão explícita de tipos
poderá ser forçada em qualquer expressão
através do operador unário cast (molde). Em
(type name) expression

Conversões de tipo – regras (5)
Se n é um int deve-se ter
sqrt ((double(n))
pois sqrt espera um double como argumento.
O typecast converte o int para double, antes de
passá-lo para sqrt.

Se forem declarados argumentos por um
protótipo de função (como normalmente deve
ser), esta declaração causará uma coerção
automática dos argumentos, quando a função for
invocada.

Ops de Incremento e Decremento
++ e - 
Podem ser usados prefixados ou pós-fixados.

++n e n++ (ambos incrementam n)
++n incrementa n antes que seu valor seja usado,
n++ incrementa n depois que seu valor foi usado.

Se n = 5
x = n++; /* atribui 5 a x */
x = ++n; /* atribui 6 a x */
em ambos os casos n torna-se 6.

Download

int