Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
CURSO DE :
LINGUAGEM C
por
FERNADO SANTOS OSRIO
So Leopoldo - 1992
1 - Introduo
1.1 - Histrico
1.2 - Caractersticas da linguagem
1.3 - Organizao deste manual
2 - Tipos de dados
2.1 - Tipos de dados pr-definidos
2.2 - Converso de tipos
2.3 - Definio de novo tipos de dados
2.4 - Tamanhos dos tipos de dados
3 - Operadores
3.1 - Operador de atribuio
3.2 - Operadores aritmticos
3.3 - Operadores lgicos
3.4 - Operadores relacionais
3.5 - Manipulao de bits
3.6 - Operadores de assinalamento
3.7 - Operadores de pr e ps incremento
3.8 - Operadores de endereo
3.9 - Tabela de operadores do "C"
3.10- Precedncia dos operadores
4 - Expresses condicionais
5 - Definies
5.1 - Constantes
5.2 - Variveis
Declarao
Tipos de variveis
Inicializao
5.3 - Converso de tipos
6 - Macros do Pr-processador
7 - Estruturas gerais
7.1 - Comandos
7.2 - Blocos
7.3 - Funes
7.4 - Programas
8 - Comandos de "C"
8.1 - If/Else
8.2 - While
8.3 - For
8.4 - Do/while
8.5 - Break
8.6 - Continue
8.7 - Switch/case
8.8 - Goto
8.9 - Sizeof
8.10 - Return
9 - Passagem de parmetros
9.1 - Parmetros do "main"
9.2 - Parmetros de funes
10 - Apontadores
11 - Estruturas
12 - Unies
13 - Funes pr-definidas
13.1 - Funes de E/S padro
13.2 - Funes de manipulao de arquivos
13.3 - Funes de uso geral
Apndices :
A - Compilador "C"
B - Padro K&R X ANSI
C - Erros mais comuns de "C"
D - Exemplos de programas
E - Exemplo de Header
Bibliografia
1 - INTRODUO :
1.1 - HISTRICO :
A linguagem "C" uma linguagem que foi criada nos laboratrios da BELL por Brian W.
Kernighan e Dennis Ritchie em 1972. Esta linguagem, teve suas idias iniciais originadas da
linguagem BCPL ( Basic Combined Programing Language ), desenvolvida por Martin Richards.
Esta influncia do BCPL se deu atravs de outra linguagem, chamada "B" e criada por Ken
Thompson em 1970 para o primeiro sistema operacional UNIX no PDP-11.
A partir de sua criao a linguagem "C" sofreu uma longa evoluo sendo que uma de
suas primeiras utilizaes foi a de reescrever o sistema operacional UNIX (1973) que estava
escrito em linguagem assembler do PDP-11. Por este motivo que se tem associado a linguagem
ao S.O. UNIX, visto que o UNIX composto atualmente, quase na sua totalidade, de programas
escritos em "C" (Sist. Operacional, utilitrios, compiladores, ...). Entretanto isto no implica que
o "C" seja uma linguagem "amarrada" a um sistema operacional ou mquina.
Devido a evoluo do "C", que seguia apenas o padro descrito por Kernighan e Ritchie,
tornou-se necessria uma padronizao mais rgida para a linguagem, permitindo a portabilidade
dos softwares escritos nesta linguagem. Isto foi feito pelo ANSI (American National
Standards Institute), criando assim o padro C ANSI.
2 - TIPOS DE DADOS :
Caracter / Byte
INT :
Inteiro
SHORT :
LONG :
FLOAT :
DOUBLE :
Pointer (*) :
Array ([ ]) :
OBS.:
- Os arrays sempre comeam na posio (ndice) zero ! Cuidado se voc definiu
um array a[10], ele ter as 10 posies de a[0] at a[9].
- Os arrays de caracteres (strings) devem ser dimensionados com uma posio
extra para o caracter de fim de string '\0'.
(nome-do-tipo)expresso
vardoub = (double)varint;
fatorial = fat((int)valor_doub);
->
->
->
->
->
->
soma
subtrao
multiplicao
diviso
mdulo da diviso (resto da diviso inteira)
sinal negativo (operador unrio)
"<" "<="
"=="
"!="
->
->
->
->
->
->
Bit and
Bit or
Bit eor - exclusive or
Shift left
Shift right
Bit not (complemento)
->
->
->
->
->
->
->
->
->
->
Soma
Subtrao
Multiplicao
Diviso
Modulo da diviso
Shift right
Shift left
And
Eor - exclusive or
Or
->
->
I = ++ I
I = -- I
Z=A;A=A+1
Z=A;A=A-1
->
->
Z = A ++
Z = A --
A=A+1;Z=A
A=A-1;Z=A
->
->
Z = ++ A
Z = -- A
|
| Parntese Colchetes Ponteiro Ponto
|
+-------------+-----------------------------------------------+
|
14
|
!
~
*
&
++
-- |
|
| Negao NOT Ponteiro Endereo Incr. Decr.|
|
|
(TYPE)
sizeof
|
|
| Converso Menos (Unrio) Tamanho
|
+-------------+-----------------------------------------------+
|
13
|
*
/
%
|
|
| Multiplic. Diviso Mdulo
|
+-------------+-----------------------------------------------+
|
12
|
+ (Soma)
- (Subtrao)
|
+-------------+-----------------------------------------------+
|
11
|
>>
<<
|
|
| Shift Left
Shift Right
|
+-------------+-----------------------------------------------+
|
10
|
<
<=
>
>=
|
|
| Menor Menor ou Igual Maior Maior ou Igual |
+-------------+-----------------------------------------------+
|
9
| ==
!=
|
|
| Igual Diferente
|
+-------------+-----------------------------------------------+
|
8
| & (Bitwise AND)
|
+-------------+-----------------------------------------------+
|
7
| ^ (Bitwise XOR)
|
+-------------+-----------------------------------------------+
|
6
| | (Bitwise OR)
|
+-------------+-----------------------------------------------+
|
5
|
&&
|
|
| AND Lgico
|
+-------------+-----------------------------------------------+
|
4
|
||
|
|
| OR Lgico
|
+-------------+-----------------------------------------------+
|
3
|
?:
|
|
| Condicional
|
+-------------+-----------------------------------------------+
|
2
|
=
+= -= *= /= %= |= ^= &= <<= >>= |
|
| Atribuio
Atribuio Combinada
|
+-------------+-----------------------------------------------+
|
1
|
,
|
|
| Vrgula
|
+-------------+-----------------------------------------------+
4 - EXPRESSES CONDICIONAIS :
As expresses condicionais se apresentam da seguinte forma :
EXPR1 ? EXPR2 : EXPR3
Esta expresso equivalente a :
SE EXPR1
ENTAO EXPR2
SENAO EXPR3
Exemplo :
#define IMIN(A,B) ((A<B)?A:B)
B = ((X == Y)?X:Y);
5 - DEFINIES :
5.1 - CONSTANTES :
No podem ter seus valores alterados aps a sua definio. Declaradas das seguintes
formas :
const <tipo_var> <nome_const> = <valor>
# DEFINE <nome_const> <valor> <== Macro do pr-processador
Exemplos de constantes :
255
0777
0XFF
nnnL
nnnU
nnnF
'c'
'CC'
->
->
->
->
->
->
->
->
\n
\b
\r
\f
\t
\v
\0
\\
\'
\"
\?
\a
\xNN
->
->
->
->
->
->
->
->
->
->
->
->
->
Decimal
* constantes Inteiras
Octal
* comeando com 0 -> Octal
Hexadecimal * comeando com 0x -> Hexa
Long
* L,U -> foram uso do tipo
Unsigned
* podem ser usados juntos
Float
* fora armazenamento como float
Caracter (seu valor o ascii de 'c' - tipo char)
Caracter ( 2 caracteres - tipo int ) (TC)
\XXX -> Octal XX (expl.: '\014' o form feed).
So esperados 3 dgitos aps o "\" !
New Line
LF 0x0A * Sequncias de escape
Backspace
BS 0x08
Carriage Return CR 0x0D
Form Feed
FF 0x0C
Tab Horiz
HT 0x09
Tab Vertical
VT 0x0B
Null
0x00
Backslash
\ 0x5C
Single quote
' 0x2C
Double quote
" 0x22
Question Mark ? 0x3F
Bell
BEL 0x07 (ANSI)
Repr. hexa
0xNN (ANSI)
2) char msg[20];
strcpy (msg,"COMO VAI ?");
A diferena est no fato de que o exemplo 1 no aloca rea para a string, e aps associa
apenas o pointer a uma rea de dados onde estar a string definida pelo programa. No exemplo 2,
j temos a rea definida, e portanto podemos us-la livremente.
5.2 - VARIVEIS :
5.2.1 - Declarao :
A declarao de variveis pode ser feita em qualquer parte do programa sempre no
incio de um bloco (aps uma "{"). Cabe aqui citarmos algumas informaes a respeito
declarao de variveis :
- Nomes de variveis comeam com uma letra ('A'..'Z','a'..'z') ou pelo underscore ('_').
- Aps podem ser seguidos dgitos, letras e underscores. No caso do TC podemos ter at
32 caracteres definindo um identificador.
- Evite o uso do '_' no primeiro caracter do identificador de uma varivel, pois este tipo de
identificadores de uso do sistema.
- Normalmente ao declararmos uma varivel esta ser inicializada com zero, como
veremos em seguida.
- So diferenciados os caracteres minsculos dos maisculos no nome de qualquer
varivel.
Declarao de variveis :
<modific> <tipo_dado> <nome_var>;
<modific> <tipo_dado> <var1,var2,...>;
ou
Expl.: extern
int
nroint;
unsigned int
n1,n2,n3;
char
letra;
5.2.3 - Inicializao :
Regras de inicializao de variveis :
- externas e estticas -> inicilizadas com "0"
- automticas e registradores -> contm lixo
Podemos tambm definir o valor inicial da varivel no momento de sua declarao, o que
feito da seguinte forma :
<modific> <tipo_dado> <nome_var> [= valor];
Exemplos :
char ch
= 'A';
int first = 1;
float balance = 123.23;
char msg[9] = "Como vai ?";
Arrays :
char num[5] = { 1, 2, 3, 4, 5 };
char str[5] = { 'A','B','C','D','E' };
char z[4][2] = { { 0, 0 }, { 0, 1 }, { 1, 0 }, { 1, 1}
{ 2, 0 }, { 2, 1 }, { 3, 0 }, { 3, 1}};
O "C" segue algumas regras para a converso de tipos de dados, converso esta que
feita para possibilitar ao compilador de realizar operaes requeridas em expresses com tipos
compatveis entre si. As regras de converso de tipos so as seguintes :
- Todos os valores no-inteiros ou no-double so convertidos como mostrado na tabela
abaixo. Aps isto os dois valores a serem operados sero ou do tipo int (incluindo long e
unsigned) ou do tipo double.
- Se um dos operandos do tipo double, o outro operando tambm ser convertido para
double.
- Por outro lado, se um dos operandos for do tipo unsigned long, o outro ser convertido
para unsigned long.
- Por outro lado, se um dos operandos for do tipo long, ento o outro operando ser
convertido para long.
- Por outro lado, se um dos operandos for do tipo unsigned, ento o outro operando ser
convertido para unsigned.
- E por ltimo, ambos os operandos sero do tipo int.
Tabela de converso : (TC)
TIPO
char
unsigned char
signed char
short
enum
float
CONVERTIDO PARA
int
int
int
int
int
double
MTODO USADO
extenso de sinal
zera o byte mais significativo
extenso de sinal
se unsigned, entao unsigned int
mesmo valor
preenche mantissa com 0's
Exemplo :
char ch;
int
i;
float f;
double d;
result = ( ch / i )
+
( f * d )
( f + i )
|
|
|
|
|
|
int |
double |
double |
\ /
\ /
\ /
int
double
double
double result;
+----double----+
|
+--------double--------+
6 - MACROS DO PR-PROCESSADOR :
As macros so instrues analisadas por um pr-processador (CPP - "C" pr-processor)
que realiza as operaes definidas. As principais macros existentes so :
#include
#define
#if
#ifdef
#endif
#line
#undef
#else
#ifndef
#elif
- Utilizao, sintaxe e exemplos :
* DEFINE : Fora a substituio dos nomes dados pelo texto de reposio, dentro do
cdigo fonte do programa. H tambm a macro-substituio com parmetros, na qual
os argumentos so trocados posicionalmente (de acordo com sua posio) e por
correspondncia. Esta operao realizada antes do incio da compilao, sendo
transparente ao compilador. Sintaxe :
#define <nome> <texto_de_reposio>
ou
#define <nome> ( argumento, arrgumento, ...> <texto_de_resposio>
As definies podem ser bem extensas podendo continuar em outras linhas com o
auxlio de uma "\" no final da linha.
Exemplo :
#define
#define
#define
#define
#define
MAXVAL 999
then
begin {
end }
max(a,b) ((a>b) ? a:b)
if (num == valor)
then begin
i++;
i++;
x = MAXVAL;
end;
else x = max (num,valor);
if (num == valor)
{
x = 999;
}
else x = ((num>valor) ? num:valor);
* UNDEF : Desfaz a definio, faz com que o pr-processador "esquea" a definio feita
anteriormente. Sintaxe :
#undef <identificador>
Exemplo : #undef MAXVAL
* INCLUDE : Causa a substituio da linha pelo contedo do arquivo informado. Inclui
um trecho de um programa contido no arquivo especificado, a partir da linha onde foi
dado o include. Sintaxe :
# INCLUDE "nome_do_arq"
# INCLUDE <nome_do_arq>
ou
-> So aceitas tanto as "" como <>
#include "arquivo"
#include <stdio.h>
* LINE : Faz com que o compilador acredite, para fins de diagnstico de erros, que o
nmero da prxima linha do fonte seja dado pelo valor constante indicado e que o nome
do arquivo corrente de entrada seja dado pelo identificador tambm indicado. Sintaxe :
#line <cte_nro_lin> [ <ident_arq> ]
Exemplo : #line 1000 ARQATUAL
7 - ESTRUTURAS GERAIS :
7.1 - COMANDOS :
Todos os comandos de "C" devem ser escritos em minsculas e devem ser seguidos de
um ";". Sintaxe : comando;
7.2 - BLOCOS :
Os blocos so definidos de uma "{" at a outra "}", equivalem aos blocos de PASCAL
definidos pelo "begin" e "end". Dentro de cada bloco podemos ento definir um conjunto de
comandos, como se fossem um s. Outra caracterstica interessante dos blocos que sempre no
incio destes (aps o "{") podemos declarar novas variveis (variveis locais ao bloco),
independentemente da posio deste bloco no programa. No pode-se por ";" aps um fim de um
bloco.
Formato : { -> incio de bloco
} -> fim de bloco
7.3 - FUNES :
So subrotinas (conjunto de comandos) que podem ser chamados de diferentes partes
do programa quando necessrio. Normalmente retornam um valor ao final de sua execuo e
podem receber parmetros de entrada para a sua execuo. Para executar uma funo basta
referenciar o seu nome. So definidas da seguinte forma :
[<tipo_ret>] <nome_da_funo> ( [<lista_argumentos>] )
[<declarao_de_argumentos>;]
{
<declaraes_locais>;
<comandos>;
[ return [ (<resultado>) ];
}
Chamada : <nome_da_funo> ( [<lista_argumentos>] );
A definio de funes NO pode ser "aninhada" ! Note tambm que quando definimos
uma funo no colocamos o ";" nesta linha. Alm de uma definio, as funes podem ter
tambm uma declarao, que servir para identificar ao compilador o tipo retornado pela
funo caso esta no retorne o tipo default (int). feito da seguinte forma :
<tipo_ret> <nome_funo> ( ); ou
<tipo_ret> <nome_funo> ( <declarao de parmetros> ); (ANSI)
Exemplo :
char *readtxt( );
double sqrt(int x);
void plot (unsigned int x1,unsigned int x2,char cor);
7.4 - PROGRAMAS :
Sua estrutura segue aproximadamente esta forma :
#include <bibliotecas>
#define <funes_de_macros>
#define <constantes>
declarao_de_funes;
definio_de_novos_tipos_de_dados;
definio_de_variveis_globais;
main ( )
{
definio_variveis_locais;
comandos;
}
/* Comentrios : texto livre */
tipo_ret funo (argumentos)
definio_de_argumentos;
{
definio_variveis_locais;
comandos;
return (varivel);
}
8 - COMANDOS DE "C" :
8.1 - IF/ELSE :
Execuo condicional de comandos. A instruo IF causa a execuo de uma ou um
conjunto de instrues, dependendo do valor resultante da expresso avaliada. Sintaxe :
if (expresso)
comando1;
[ else
]
[ comando2;]
- As instrues de execuo condicional dependem da avaliao de uma expresso
condicional. Esta expresso composta por vrias operaes, que so efetuadas atravs dos
operadores lgicos e relacionais, devolvendo um valor booleano TRUE ou FALSE. No "C" a
expresso condicional pode devolver um valor inteiro, que ter o seguinte significado :
0 - FALSE
No Zero - TRUE.
- Expresso : uma sequncia de operadores lgicos, relacionais, aritmticos e
valores. Pode possuir atribuies e chamadas de funes, que sero interpretadas como valores
comuns e devem vir entre parnteses. Na atribuio o valor avaliado ser o valor atribudo e na
chamada de funo o valor retornado. Tambm podemos ter listas de comandos dentro de
uma expresso, separados por vrgulas (','), e que sero avaliados da esquerda para a direita,
sendo o ltimo comando o que indicar o valor a ser interpretado na expresso. Exemplos :
((sum = 5 + 3) <= 10)
((ch=getch( )) == 'Q')
(oldch=ch,ch=getch( ))
8.2 - WHILE :
Enquanto a condio descrita pela expresso for satisfeita (verdadeira) o comando
ser repetido. A avaliao da expresso realizada da mesma forma que no comando IF. O
comando WHILE o nico (e o principal) comando de repetio realmente necessrio, sendo
que pode substituir qualquer outra construo do tipo : FOR, REPEAT/UNTIL, DO/WHILE, GOTO
...
Sintaxe : while (expresso)
comando;
8.3 - FOR :
O comando FOR serve para a execuo de um nmero fixo de vezes, enquanto uma
varavel percorre uma determinada faixa de valores. Esta varivel chamada de varivel de
ndice. Sintaxe :
for (incio; condio; modific)
comando;
ou
for (expr1,expr2,...;expr3,...;expr4,...)
comando;
Onde temos "incio" como sendo uma expresso que ir gerar o valor inicial da varivel
de ndice utilizada pelo comando. A "condio" ir nos indicar uma condio para o
prosseguimento do loop (enquanto tal condio for verdadeira ir repetir o loop). E finalmente
"modific" ser o comando dado para cada execuo do loop, sendo este realizado ao final de um
loop do FOR, modificando o valor da varivel de ndice, antes de um novo teste da condio.
Como pode ser visto no segundo formato do comando FOR, cada um destes elementos
(incio,condio e comando) pode estar dividido em sub-comandos, como nas expresses do IF.
Para criarmos um loop infinito (sem fim) podemos fazer um comando FOR da seguinte
forma : FOR ( ; ; ) - comando sem expresses de controle. O comando for equivalente a
seguinte estrutura :
incio;
while (condio)
{
comando;
modific;
}
8.4 - DO/WHILE :
O comando DO/WHILE o inverso do comando WHILE, ou seja o teste executado ao
final deste ao invs de ser no incio. Este comando tambm equivalente ao comando
REPEAT/UNTIL (Pascal) s que a expresso avaliada em um estaria negada em relao ao outro.
Sintaxe :
do comando
while (expresso);
O comando ser executado e depois ser testada a condio dada pela expresso, e
caso esta seja verdadeira (TRUE) ser novamente executado o comando.
8.5 - BREAK :
Causa a sada no meio de um loop (para comandos : for, while, do, switch). Provoca a
antecipao do fim do loop. muito usado com o comando CASE como ser visto mais adiante.
8.6 - CONTINUE :
Comando para a re-execuo do loop, a partir do teste. Ir causar a reinicializao do lao
(no funciona para o switch). Um exemplo prtico de seu uso pode ser visto abaixo :
while (x <= valmax)
{
printf ("Entre com valor : ");
scanf ("%d",val);
if (val < 0)
continue;
...
}
8.7 - SWITCH/CASE :
Faz uma associao de valores com comandos a executar. Conforme o valor dado,
executa um certo nmero de instrues. Serve como uma estrutura mais sofisticada que os IF's
encadeados :
if (valor == x)
comando1;
else if (valor == y)
comando2;
else if (valor == z)
comando3;
...
else comando;
Sintaxe :
switch (varivel)
{
case <valor1> : <comando1>;
case <valor2> : <comando2>;
case <valor3> :
case <valor4> : <comando3>;
<comando4>;
...
case <valor5> : comando5;
[ default
: comando6; ]
}
devem ser do tipo inteiro (compatvel). No poderemos ter valores como : float, double, strings e
pointers.
O uso do comando BREAK muito importante quando associado ao SWITCH, pois caso
este no seja usado a cada CASE, ser feita execuo de todos os comandos at encontrar o fim
do SWITCH, sendo executado inclusive o DEFAULT se houver. Por isso a estrutura comumente
usada em um comando CASE ser como :
case 'A' : x++;
break;
case 'B' :
case 'b' : y++;
break;
8.8 - GOTO :
Desvio incondicional do fluxo de execuo de um programa para um determinado
ponto apontado por label.
Sintaxe :
goto <label>;
<label>: <comandos>
8.9 - SIZEOF :
uma funo da linguagem que ir nos fornecer um inteiro que igual ao tamanho do
objeto especificado, tamanho este dado em bytes.
Sintaxe :
sizeof (objeto)
8.10 - RETURN :
Usado para retornar de uma funo, normalmente retornando um parmetro para a funo
que a chamou.
Sintaxe :
return;
return (parmetro);
ou
9 - PASSAGEM DE PARMETROS :
9.1 - PARMETROS DO "MAIN" :
O mdulo principal do programa (main) pode receber dois parmetros externos
opcionais, so eles : ARGC e ARGV. Sintaxe utilizada :
main (argc, argv)
int argc;
char *argv[ ];
Onde temos :
ARGC - Nmero de apontadores
ARGV - Array de apontadores para cadeias de caracteres que contm os argumentos.
Teremos em argc um valor maior que zero caso hajam parmetros pois argv[0] nos d o
nome pelo qual o programa foi chamado. O exemplo abaixo mostra a associao dos parmetros
:
A>prog_c param1 b:param2 xyz
ARGC = 3 e
- Temos ainda o tipo de dado (ANSI) que indica um tipo de dado indefinido ou inexistente :
VOID . Exemplos de uso do void :
void myfunct(arg1,arg2)
double nro_rand(void);
void init(void)
- Quando fazemos um "prototype" de uma funo com um nmero varivel de
parmetros, podemos usar "..." para indicar esta indefinio quanto ao nmero exato de
parmetros (ANSI).
* Exemplos de funes e suas chamadas :
soma (a,b)
int a,b;
->
x = soma (10,21)
BY VALUE
readval(a,b)
long *a,*b;
->
long val1,val2;
readval(&val1,&val2)
BY REFERENCE
init ( )
->
init( );
SEM PARMETROS
int x;
x = (int)raiz(val);
CONVERSO
10 - APONTADORES : (Pointers)
Os apontadores ou pointers so tipos de dados que tem por funo "apontar"
(referenciar) variveis atravs de seus endereos fsicos (posio da varivel na memria),
permitindo uma maior flexibilidade em nossos programas como : acesso indireto por ponteiros,
passagem de parmetros By Reference, alocao dinmica de memria, criao de listas
encadeadas e outras estruturas de dados mais complexas.
So declarados da seguinte forma :
int x,y;
/* Declarao de dois inteiros */
int *px;
/* Declarao de um pointer para inteiros */
double vard, *pd;
Os pointers so definidos em funo do tipo de varivel ao qual ele ser ligado, so
pointers do tipo "aponta para um dado tipo de dado". Como se usa um pointer :
pt = &x
y = *pt
*pt = 12
int var[5],*pint;
ptr = var
/* ptr aponta para var[0] */
ptr = *(ptr+2); /* ptr aponta para var[2] */
Como j pode ser visto a indexao dos arrays feita da mesma maneira em que se
trata com pointers. Ento, incrementar um pointer significa somar ao endereo atual do pointer
tantas unidades quanto for o tamanho do tipo de dado apontado, assim como para o endereo de
um elemento de um array pode ser obtido apenas somando-se tantas unidades quanto for o
tamanho do elemento do array. Note a equivalncia :
<tipo> var[100],*ptvar;
(ptvar + i) == &(var[i])
*(ptvar + i) == var[i]
(ptvar + i) ==> Deslocamento de i*sizeof(var) sobre end. atual
Portanto podemos fazer somas e incrementos com pointers operando como se fossem
meros endereos sendo que no caso de incrementos, o acrscimo ser feito de acordo com tipo
de dado ao qual o pointer atua (soma tantos bytes quanto for o tamanho do tipo).
Como foi visto, pointers acessam diretamente a memria do micro, por isso constituem
uma ferramenta poderosa mas ao mesmo tempo perigosa, pois um descuido qualquer pode
causar srios danos. Sempre que fomos usar um pointer ele j dever ter sido inicializado, ou
seja, j deve ter sido atribudo algum endereo a ele. Outro cuidado a ser tomado quanto a
precedncia de operadores, pois comum a confuso em casos como estes :
int (*array)[13];
int *array [13];
11 - ESTRUTURAS :
As estruturas so conjuntos (agrupamentos) de dados, que definem um novo tipo de
dado mais complexo, formado por tipos de dados mais simples. As estruturas podem ser definidas
das seguintes formas :
struct tipo {
tipo_var nome_var;
tipo_var nome_var;
...
} nome_da_estrutura;
OU
struct {
tipo_var nome_var;
tipo_var nome_var;
...
} nome1,nome2,...;
OU
struct tipo {
tipo_var nome_var;
tipo_var nome_var;
...
};
struct tipo nome1,nome2,...;
OU
typedef struct {
tipo_var nome_var;
tipo_var nome_var;
...
} record;
record nome1,nome2,...;
Exemplo :
struct data {
int dia,mes,ano,dia_ano;
char nome_mes[10];
};
struct data today = { 3, 9, 1987, 250, "novembro" };
* Referncia a um elemento da estrutura :
nome_estrut.elemento ==> data.dia = 23;
(*ptrname).elemento ==> (*ptrdt).dia = 10;
ptrname->elemento ==> ptrdt->dia = 5;
* Caractersticas das estruturas :
- Nao podem ser inicializadas na declarao ou copiadas atravs de uma atribuio.
- Podem ser acessadas com o auxlio de pointers. Permitem a criao de listas
encadeadas (Vide programa exemplo - Apndice A).
* Array de estruturas :
struct tipo1 { tipo2 nome_elemen; ... } arranjo [x];
|
|
|
tipo_estrut tipo_elemen
nome_estrut
* Estrutura de bits : (Bitfields)
struct {
unsigned nome1 : numero_bits;
unsigned nome2 : numero_bits;
...
} nome_estrut;
Exemplo :
struct
{
unsigned flag1 : 1;
unsigned doisbit : 2;
} flags;
12 - UNIES :
alocado para este tipo de dados o espao para a varivel de maior tamanho, sendo
todas variveis alocadas na mesma rea de memria e s podendo existir fisicamente uma das
variveis por vez. Sintaxe :
union tipo_uni_o {
tipo_var nome_var;
tipo_var nome_var;
...
} nome_uni_o;
O acesso feito como so acessadas as variveis de uma structure, como mostrado no
exemplo abaixo :
typedef union {
int word;
struct {
char lob;
char hib;
} byte;
} worb;
worb myvar;
myvar.word = val_int;
myvar.byte.lob = val_byte;
myvar.byte.hib = val_byte;
- Esta estrutura equivale a contruo de "variant record" ou "variant fields" existente na
liguagem Pascal.
13 - FUNES PR-DEFINIDAS :
As funes pr-definidas do "C", so definidas nos arquivos header (com extenso ".H"),
sendo que exitem diversos header's padro no "C", entre eles podemos citar alguns :
CTYPE.H
STDIO.H
DOS.H
STRING.H
MATH.H
G
P
%
Exemplo :
printf ("\nResultado :%3.2f",num);
printf ("Frase : %s\nContador = %x",string);
printf ("a : %-5Db : %-5Dc : %-5D",a,b,c);
* PUTS : Sada de uma string na sada padro. A string ser adicionada com um
caracter '\n'. Equivale a : printf ("%s\n", string). Sintaxe : puts (string);
* GETS : L uma string da entrada padro. Anloga a funo puts, mas em sentido
inverso.
Sintaxe :
string = gets( );
Leitura (open)
Escrita (rewrite)
Adio (append)
Para atualizar um arquivo (read e write)
Para criar um arquivo para atualizao
Adio, em arquivo para leitura e escrita
A funo fopen dever retornar um valor que poder ser o valor de um apontador para o
arquivo ou NULL em caso de erro na abertura do arquivo. Todas as outras operaes sobre os
arquivos sero referenciadas atravs deste "apontador de arquivo".
Existem certos tipos de apontadores de arquivos padro os quais so constantes :
STDIN - Entrada padro (normalmente teclado)
STDOUT - Sada padro (normalmente vdeo)
STDERR - Sada padro de mensagens de erro (Vdeo)
* GETC : L um caracter de um arquivo indicado pelo pointer de arquivo. Retorna o
prximo caracter lido do arquivo apontado por file_pointer. No caso de encontrar o fim do arquivo
retorna EOF.
Sintaxe :
carac = getc (file_pointer);
* PUTC : Escreve um caracter em um arquivo. Escreve o caracter na prxima posio do
arquivo apontado por file_pointer. a operao inversa de getc.
Sintaxe :
putc (caracter, file_pointer);
* UNGETC : "Devolve" o ltimo caracter lido do arquivo. Devolver o caracter dado, para
o arquivo apontado pelo file_pointer. Apenas um caracter devolvido ser aceito (Coloca em um
buffer temporrio de um caracter) por cada arquivo.
Sintaxe :
* Funes anlogas :
isdigit (c)
isspace (c)
isascii (c)
isprint (c)
- Verifica se um dgito
- Verifica se caracter de espao
- Verifica se caracter ASCII
- Verifica se caracter de impresso
- arquivo fonte
- arquivo objeto
- arquivo executvel
Compilao :
- No Turbo C temos um ambiente integrado de desenvolvimento de programas onde se
encontram reunidos o compilador "C" o linker e um editor de textos.
- No Microsoft C / Lattice, h a necessidade de se executar dois passos de compilao
(MC1 e MC2), e a ligao (Link). Sugerimos o uso de discos virtuais para o trabalho com este tipo
de compilador e a compilao pode se dar com o uso de um programa ".BAT" como o listado
abaixo :
echo off
mc1 %1
if errorlevel 1 goto msg1
mc2 %1
if errorlevel 1 goto msg2
link cs+%1,%1,nul,mcs
if errorlevel 1 goto msg3
goto fim
:msg1
echo **** Erro no primeiro passo da compilacao ****
goto fim
:msg2
echo **** Erro no segundo passo da compilacao ****
goto fim
:msg3
echo **** Erro na linkagem do programa ****
:fim
- Em ambos os compiladores temos os seguintes arquivos :
Compilador (TC.COM ou MC1 e MC2)
Linker (Link)
Biblioteca de funes (Arquivos com extenso ".H")
Biblioteca de objetos (Arquivos com extenso ".OBJ")
- O Microsoft C encontrado em diferentes verses :
Microsoft 3.0 / Lattice
Microsoft 4.0 + Codeview (depurador)
Microsoft 5.0
Ao ser criada a linguagem "C" por Kernighan e Ritchie, foi definido um padro, padro
este que se encontra descrito no livro "base" para a programao em "C", escrito por K&R. Mas
aps a disseminao do uso do "C" e tornou necessria uma melhor padronizao e criao de
outras estruturas mais flexveis, isto se deu atravs da padronizao ANSI. Este padro mais
recente e alguns compiladores ainda no o seguem, mas a tendncia que todos os
compiladores "C" passem a seguir o padro ANSI.
Vamos aqui descrever as principais diferenas entre o padro K&R em relao ao padro
ANSI, citando vantagens e desvantagens apresentada por ambos :
* Function Prototypes : So uma forma mais eficiente de declarao de funes, pois
permitem ao compilador fazer uma verificao mais consistente a respeito das funes e seus
parmetros de entrada. Exemplos de declaraes de funo :
char *myfunct ( );
char *myfunct (int arg1,char arg2,char *arg3);
==> K&R
==> ANSI
Com o uso do "prototype" uma funo poder ser chamada no programa antes de ser
definida, mas mesmo assim o compilador ter condies de informar ao programador quanto a
erros referentes a passagem de parmetros de tipo incompatvel e em nmero insuficiente ou
superior ao nmero real de parmetros necessrios a funo. Assim como a declarao feita
com o uso desta notao podemos ter a definio desta forma :
char *myfunct ( )
int arg1;
char arg2,*arg3;
{ ... }
==> K&R
==> ANSI
sun 0
mon 1
tues 2
wed 3
thur 4
fri 5
sat 6
==> K&R
typedef enum (sun, mon, tues, wed, thur, fri, sat ) days;
days todays,date;
==> ANSI
* Constantes : Com o modelo K&R s podemos declarar constantes com o uso da macro
#define, que far a substituio dos itens declarados nele pelos seus respectivos valores. No
padro ANSI temos a possibilidade de declarar um novo tipo de dado - o "const". As variveis
declaradas como sendo "const" no podero sofrer modificaes como : incremento,
decremento, atribuio, ... A diferena principal entre constantes e defines que as constantes
esto alocadas em memria, como as variveis. Exemplos :
#define PI 3.1415926
const float pi = 3.1415926;
==> K&R
==> ANSI
As constantes sero protegidas contra os acessos indevidos, mas claro que atravs de
pointers podemos modificar seus valores e no teremos como evitar. Por exemplo :
pi = 3.0;
/* Invlido : atribuio a constante */
pi = pi++;
/* Invlido : incremento de contante */
str = "Hello";
/* Invlido : atribuio de novo end. */
strcpy(str,"Hello"
/* Vlido : alterao por pointers ! */
* Itens constantes : O padro ANSI aceita as seguintes estruturas abaixo que no so
aceitas pelo padro K&R.
msg = "Primeira frase." /* Definir strings que ocupem
*/
"Segunda frase."
/* vrias linhas ...
*/
'\x0a'
/* Sequncia de escape em Hexa */
* Declarao Void : O tipo de dado "void" , usado somente nas declaraes e
definies de funes serve para identificar um tipo nulo. H dois significados para o "void" : no
h retorno de parmetros pela funo ou a funo retorna um valor genrico (pointer para qualquer
tipo de dado). Exemplos de uso do "void" :
void myfunct( );
/* Myfunct no retorna valores
*/
int Myfunct(void);
/* Myfunct no possui parmetros */
void *Myfunct( );/* Retorna pointer genrico
*/
* Modificador Signed : O padro ANSI permite alm do modificador "unsigned" um
outro modificador equivalente a este, mas de sentido contrrio, o "signed", que indica que o
dado do tipo com sinal.
* Modificador Volatile : Definido pelo padro ANSI serve para indicar o oposto do "const",
pois esta varivel poder ser modificada a qualquer momento, no apenas por vo, mas por
algo "externo", como uma rotina de interrupo ou porta de I/O. Esta declarao previne o
compilador para evitar o uso desta varivel em um registrador. Exemplo :
volatile int ticks;
timer ( )
/* Rotina de atendimento da */
{
/* interrupo do timer
*/
ticks++;
}
Incorreto
Correto
Correto
Incorreto
- O erro acima citado muito comun e pode ser generalizado como sendo a passagem
incorreta de parmetros, passando dados como endereos e endereos como dados.
- Um erro muito comum o de aps a definio do nome de uma funo ou procedure
incluirmos um ';' , o que ir gerar um erro de sintaxe. Exemplo :
main ( );
{ ... }
- Est incorreto
- Um pointer para caracter no aloca rea, portanto no pode ser usado em comandos
como scanf ou strcpy, sem a devida alocao da memria necesria.
{
nodoptr = nodoptr->prox;
printf ("%s\n",nodoptr->texto);
}
printf ("\n\n>>> FIM DA LISTAGEM DE DADOS\n\n");
}
/* read flag */
/* write flag */
/* non-buffered flag */
/* private buffer flag */
/* end-of-file flag */
/* error flag */
#define NULL 0
#define FILE struct _iobuf
#define EOF (-1)
BIBLIOGRAFIA
1 - The "C" Programming Language
Brian W. Kernighan & Dennis M. Ritchie
Englewood Cliffs. Prentice - Hall, 1978.
(Edio em portugus - Editora Campus)
2 - Turbo C User's Guide
Borland International Inc. California - USA, 1987.
3 - Turbo C Reference Guide
Borland International Inc. California - USA, 1987.
4 - Linguagem "C" - Guia do Usurio
Hebert Schildt
Ed. McGraw-Hill, 1985
5 - Microsoft C compiler - Reference Manual
Microsoft Corporation, 1983.