Você está na página 1de 19

Introdução à Linguagem C

A linguagem C, desenvolvida em paralelo com o UNIX é atualmente uma das


linguagens de programação mais utilizadas. Suas principais características são:
• Simples e de aprendizado fácil.
• Uso amplamente difundido.
• Baseada em construções simples, que usam os recursos da máquina de forma
eficiente.
• Oferece recursos de modularização necessários ao desenvolvimento de aplicações
de grande porte.
• Disponível em várias plataformas.
Um programa simples
O programa abaixo é o clássico "Hello, world", usado na maioria dos textos
introdutórios para descrever a "cara" de um programa em C:

#include <stdio.h>
int main()
{
printf("Hello, world\n");
}
O que este programa faz é basicamente escrever na saída padrão o string "Hello, world".
Alguns detalhes deve ser explicados:

#include <stdio.h> Indica que este programa deve utilizar as


definições feitas no arquivo 'sdtio.h' para
as funções básicas de entrada e saída.

int main() { ...} Corresponde ao "corpo" do programa. É a partir


dele que se inicia a execução do programa.

printf(...) Comando que indica "escreva o texto entre


parêntesis através de um dispositivo de saída
(neste caso, a saída padrão).

"Hello, world\n" Cadeia de caracteres (string). A seqüência de


caracteres '\n' representa o caracter newline.

Outro exemplo:
Variáveis, constantes, expressões e atribuição
O exemplo a seguir ilustra alguns conceitos importantes em C:

#include <stdio.h>
int main()
{
int a,b,c,soma;

a = 1; b = 2; c = 3;
soma = a + b + c;
printf("soma = %d\n",soma);
}

Nesse exemplo, o comando

1
int a, b, c, soma;
declara a, b, c e soma como variáveis do tipo inteiro. Uma variável do tipo inteiro pode
receber qualquer valor inteiro permitido na máquina. Os comandos

a = 1; a = 2; c = 3;
são comandos de atribuição. Um comando de atribuição indica que uma variável assume
passa a assumir o valor de uma expressão. Nos comandos acima, as expressões são
definidas pelas constantes inteiras 1, 2 e 3. Esses comandos são executados na ordem
em que aparecem. Ao atribuir um valor a uma variável, o valor anterior da mesma é
simplesmente perdido (uma variável sempre tem um único valor. Considere-se por
exemplo a sequência de comandos abaixo:
a = 1; a = 2; a = 3;
Após a execução dessa sequência de comandos, o valor de a será igual a 3 (a cada
atribuição, o "valor anterior" da variável a é destruído). O valor de uma variável pode ser
utilizado numa expressão ( soma=a+b+c ). Isso vale também para a variável à esquerda
do sinal de atribuição ("=").
Exemplo:

a = 1;
a = a + 2;
a = a + 3;
Em C, todo comando encerra com um " ; ". A separação de linhas tem a mesma função
que um espaço em branco. A sequência de comandos acima é equivalente a

a = 1; a = a + 2; a = a + 3;
O comando printf
O comando printf é utilizado para escrever dados em forma de texto na saída padrão ou
num arquivo. Por enquanto, estamos utilizando a forma mais simples desse comando:

printf(< sequência de caracteres entre aspas > , variável1, variável2, ...);


Nessa forma, os caracteres da sequência são escritos na saída padrão. Ao serem
escritos, alguns caracteres têm um significado especial. Por exemplo o caracter '%' é
usado para indicar que o caracter seguinte é um especificador de formato, e ambos
devem ser substituídos pelo valor de uma variável da lista de variáveis. Por exemplo, no
comando

printf("o valor de a é : %d", a)


o par de caracteres '%d' será substituído pelo valor da variável a. O caracter 'd' indica que
esse valor deve ser escrito como um número inteiro decimal. Outro exemplo(completo):

#include <stdio.h>
int main()
{
int a,b,c;

a = 1; b = 2; c = 3;
printf("valor de a:%d valor de b: %d valor de c:%d \n ",a,b,c);
}

Neste exemplo, a primeira ocorrência de "%d" se refere à primeira variável da lista (a), a
segunda à segunda variável (b) e assim sucessivamente. O par "\n" está sendo utilizado

2
para representar o caracter new line que causa a mudança de linha na saída padrão. O
resultado da execução desse programa deverá ser:

valor de a:1 valorde b:2 valor de c:3


Entrada de Dados
No exemplo abaixo, o comando scanf está sendo usado para entrada de dados. Seu uso
é semelhante ao uso do printf: o primeiro argumento é uma cadeia de caracteres na qual
o par "%d" indica um valor inteiro decimal. Os valores lidos são associados às variáveis
que aparecem a seguir. Os nomes das variáveis aparecem precedidos de '&'.

#include
int main()
{
int a,b,c;
scanf("%d %d %d", &a,&b,&c);
printf("a:%d b:%d c:%d \n",a,b,c);
}

Os 'comandos' scanf e printf na verdade são funções definidas na biblioteca stdio que
internamente chamam funções da biblioteca padrão que por sua vez se utilizam dos
serviços oferecidos pelo sistema operacional para realizar as operações de leitura e
escrita.
As funções scanf e printf trabalham basicamente com sequências de caracteres. Elas
têm a capacidade de converter caracteres para outros tipos de dados e vice-versa. Essa
conversão é indicada na sequência de caracteres através de "especificadores de
formato", sempre precedidos de '%'. Nos exemplos apresentados até aqui, utilizamos
apenas "%d" para indicar a conversão de caracteres para inteiros (no caso de scanf) ou
de inteiros para caracteres (no caso de printf).
O caractere '&' antes do nome de cada variável a ser lida indica referência ou endereço
da variável. É através dessa referência ou endereço que o valor da mesma será
atualizado após a leitura do dado correspondente.

Um pouco mais sobre expressões


Nos exemplos anteriores, foram utilizadas expressões aritméticas simples como "a+1",
"a+b+c". Expressões são formadas por operandos ou operadores. Operandos são
valores (até o momento, inteiros), que aparecem na expressão como constantes,
variáveis ou expressões. A linguagem dispõe de um grande número de operadores, mas
temporariamente vamos nos restringir aos operadores aritméticos:
+ soma
- subtração
* multiplicação
/ divisão
% resto da divisão

Parentesis podem ser utilizados para forçar o cálculo de uma expressão numa
determinada ordem. Exemplos:
a + (b / 2)
(a * 2) + 1
((((a*2) + 1)*2)+1)*2+1)

3
Uma expressão como a + b * c será calculada como a + ( b * c ) porque o cálculo da
mesma leva em conta a precedência entre os operadores. Em C essa precedência é
definida da seguinte forma (para os operadores aritméticos):

+, - menor precedência
*, /,% maior precedência
Os "operadores combinados"
Em programação, são frequentes comandos como:
a = a + b;
x = x - y;
p = p * 2;
Nesses comandos, o valor a ser atribuído à variável à esquerda é o resultado de uma
operação na qual o valor dessa mesma variável é utilizado. Em C é possível escrever
esse comando de forma mais compacta através da "combinação" da operação\ com a
atribuição (+=, -=, *=, etc.). Os comandos mostrados acima, por exemplo, poderiam ser
reescritos como:

a += b;
x -= y;
p *= 2;
Os operadores ++ e --
Outro tipo de comando comum em programação é aquele no qual apenas se incrementa
ou decrementa o valor de uma variável de 1. Em C é possível escrever esse tipo de
comando através dos operadores "++" e "--". Exemplos:

++i; equivalente a i = i + 1;
++i; equivalente a i = i - 1;
Esses operadores podem ser utilizados de duas formas: antes ou depois do operando (p.
ex. ++i ou i++). No primeiro a operação é feita antes do uso do valor do operando. No
segundo caso, a operação é feita depois do uso do valor. Exemplos:

i = 10; v = ++i; /* o valor atribuído a v é 11 */


i = 10; v = i++; /* o valor atribuido a v é 10 */
/* nos 2 casos, o valor final de i é 11 */

Comentários
Um comentário em C tem a seguinte forma:

/* texto qualquer */
Comentários podem aparecer em qualquer lugar do programa onde caberia um
espaço (' '). Seu significado é exatamente o mesmo de um espaço em branco.
Comentários delimitados por "/*" e "*/" podem ocupar várias linhas.

Um exemplo: Cálculo do peso ideal


O programa abaixo calcula o "peso ideal" de uma pessoa a partir da sua altura, segundo
uma fórmula. Note que se trata apenas de um exemplo de programação e não deve ser
utilizado para orientar uma dieta.

4
#include <stdio.h>
/*
Determina o "peso ideal" de uma pessoa a partir da sua altura.
Trata-se apenas de um exemplo de programação - não segue nenhuma
orientação médica.
*/

int main()
{
int a; /* altura */
int p; /* peso */

printf("Altura em centímetros(entre 120 e 200):");


scanf("%d",&a);

p = (a-119)*5/8+45;
printf("Peso ideal: %d \n",p);
}
O Comando Condicional
O comando condicional permite alterar a sequência de execução dos comandos com
base numa condição. O comando condicional em C tem duas formas básicas:

if( condição ) comando


if( condição ) comando1 else comando2

A condição é uma expressão qualquer, cujo valor é calculado ao se executar o comando


condicional. Um valor diferente de zero para condição indica verdadeiro e um valor igual a
zero indica falso.
Na primeira forma a execução do comando condicional implica em:
1. Cálculo da expressão que define a condição.
2. comando será executado somente se o valor dessa expressão indicar verdadeiro.
A execução do comando condicional na segunda forma implica em:
1. Cálculo da expressão que define a condição.
2. Se a expressão indicar verdadeiro, comando1 será executado.
3. Se a expressão indicar falso, comando2 será executado.
Exemplos:
...
if(a - 10) b = 0;
...
if(a) b = 1; else b = 2;
...
Operadores Relacionais
Os operadores relacionais permitem a comparação de valores. São os seguintes:

< "menor que"


<= "menor ou igual a"
== "igual a"
!= "diferente de"
>= "maior ou igual a"
> "maior que"

5
Exemplos:
...
a < (h+5)
...
a <= h
...
x == 10
...
if ( a > 200) printf("altura acima do limite\n");
...
if ( a < 40) printf("altura abaixo do limite\n");
...
Esses operadores têm todos a mesma precedência, que é menor que a precedência dos
operadores aritméticos. O resultado de uma comparação será um valor igual a zero de a
condição testada resultar em falso ou um valor diferente de zero se a condição testada
resultar em verdadeiro. O valor diferente de zero indicando verdadeiro não é especificado
na definição da linguagem.
Mais exemplos
...
if(a != b) a = a-b; else b = b - a;
...
if(a != b) a -= b; else b -= a;
...
if(x == 10) y = 1;
else if (x == 11) y = 2;
else y = 0;
...

Comando Composto
Em algumas situações é necessário tratar uma sequência de comandos como um único
comando. Isso é possível através de '{' e '}', que delimitam um comando composto.
Exemplo:
...
if(a < b) { t = a; a = b; b = t; }
else i = i+1;
...

O Comando while
O comando while tem a forma

while( condição ) comando

e indica que comando deve ser executado repetidamente enquanto condição tiver tiver
um valor diferente de zero (verdadeiro). A condição é calculada antes da execução de
comando e recalculada antes de cada repetição.

6
Exemplo
#include <stdio.h>

/* calculo da soma dos números de 1 a 10 */

int main()
{
int s,i;

s = 0; i = 1;
while(i <= 10) { s = s + i; i = i+1; }

printf("A soma dos inteiros de 1 a %d é %d\n",i,s);


}
O comando while do exemplo acima poderia ser escrito de forma mais compacta:

while(i <= 10) s += i++;


Neste exemplo, o comando que se repete é um comando composto. Qualquer comando
da linguagem poderia ser utilizado nesse contexto (até mesmo um comando while).

Outro exemplo: máximo divisor comum


#include <stdio.h>

/* cálculo do máximo divisor comum de dois valores lidos */

int main()
{
int A,B, a,b;

/* leitura dos dois valores A e B */


scanf("%d %d",A,B);
a = B; b = B;
while(a!=b) if(a > b) a -= b; else b -= a;

printf("O mdc entre %d e %d é: %d\n",A,B,a);


}
Neste exemplo, os nomes 'A' e 'a' representam nomes diferentes, já que em C, os
caracteres maiúsculos são diferentes dos minúsculos ("Nome" e "nome" são
identificadores diferentes).
Ao executar while(a!=b)..., se a condição testada for falsa na primeira vez, o comando
if(a>b) a -= b; else b -= a; não será executado nenhuma vez. Isso vai acontecer se os
valores lidos para 'A' e 'B' forem iguais.

O comando for
O comando for é outro tipo de comando repetitivo, com uma estrutura um pouco mais
elaborada. Sua forma geral é a seguinte:

for(expressão1; expressão2; expressão3) comando

7
onde
• expressão1 é calculada uma vez antes do início da execução
• expressão2 indica a condição de repetição
• expressão3 é executada a cada passo, depois de comando
O comando for, como mostrado acima é equivalente a um comando while da forma:
expressão1;
while( expressão2 )
{
comando
expressão3;
}
O termo expressão1 está sendo utilizado acima em lugar de comando. A rigor um
comando em C é uma expressão, que devolve um valor. Essa característica ainda não
está sendo utilizada neste texto.
Exemplo
#include <stdio.h>

/* calculo da soma dos números de 1 a 10 */

int main()
{
int s,i;

s = 0;
for(i=1; i <= 10; ++i) s+=i;

printf("A soma dos inteiros de 1 a 10 é %d\n",i,s);


}
Esta forma de uso do comando for, na qual uma variável é usada como contador do
número de vezes que o comando é repetido ocorre com frequência na prática.
Constantes simbólicas
Em C é possível definir constantes usadas com frequência num programa através da
diretiva define. Sua forma geral é
#define nome valor
Após a sua definição, a constante pode ser usada no programa através do seu nome.
Esse recurso torna os programas mais legíveis e se bem utilizado, facilita a sua
manutenção. Exemplo:

#include <stdio.h>

/* calculo da soma dos números de 1 a N */

# define N 10

int main()
{
int s,i;

s = 0;
for(i=1; i <= N; ++i) s+=i;

8
printf("A soma dos inteiros de 1 a %d é %d\n",N,s);
}

Vetores
Um vetor é um sequência de valores de um mesmo tipo que podem ser acessados a
partir da sua posição. Exemplo: declaração de um vetor de inteiros, com 10 elementos:
...
int v[10];
...
Os elementos de um vetor podem ser acessados a partir da sua posição, ou índice, e
usados no programa como qualquer outra variável. Os índices de um vetor de N
elementos variam de 0 a N-1 (0 corresponde ao primeiro elemento e N-1 corresponde ao
último).
Exemplos
...
v[0] = 1;
v[1] = 2;
v[2] = v[0] + v[1];
...
O índice para acesso ao elemento de um vetor pode ser uma variável ou uma expressão
inteira. Exemplos:
...
for(i=0; i < N; i++) v[i] = 0;
...
v[n-k+1] = v[n-k+i];
...
Outro Exemplo
/*
leitura de uma sequência de 10 valores e determinação do maior e menor elemento
*/
#include <stdio.h>
int main()
{
int t[10];
int i, max, min;

/* leitura dos elementos do vetor */


for(i=0; i<10; i++)scanf("%d", &t[i]);

max = t[0]; min = max;


for(i=1; i<10; i++)
{
if(t[i] > max) max = v[i];
if(t[i] < min) min = v[i];
}

printf("maior valor: %d e menor valor: %d \n",max,min);

9
Valor Inicial de um Vetor
Ao declarar uma variável é possível definir um valor inicial para a mesma. Exemplo:

int k = 21;
Isso é possível também no caso de um vetor e nesse caso, a sequência de valores
aparece entre '{' e '}', separados por vírgula. Exemplo:

int dias[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 }


Vetores Multidimensionais
Em C é possível declarar um vetor no qual cada elemento é por sua vez um vetor. Através
desse recurso é possível criar vetores multidimensionais. Uma matriz bidimensional é
basicamente um vetor em que cada elemento é um vetor. Exemplo: #include <stdio.h>
int main()
{
int tab[5][10];
int i,j,k;
k = 1;

/* criação da tabela */
for(i = 0; i < 5; i++)
for(j = 0; j < 10; j++) tab[i][j] = k++;

/* escrita da tabela */
for(i = 0; i < 5; i++)
{
for(j = 0; j < 10; j++) printf(" %d ",tab[i][j]);
printf("\n");
}
}

Outros tipos de dados


Os exemplos mostrados até agora manipulavam valores (constantes e variáveis) do tipo
inteiro. Em C os tipos básicos de dados são os seguintes:
• char - representa um caracter
• int - representa um valor inteiro simples
• float - um valor em ponto flutuante, com precisão simples
• double - um valor em ponto flutuante, com precisão dupla.
Além disso, os modificadores short e long são aplicáveis ao tipo inteiro, indicando inteiros
curtos ou inteiros longos.

Exemplos
#include <stdio.h>

int main()
{
float valor = 100.0;
float taxa = 0.005;
int n = 12;
int i;

10
printf("valor inicial: %7.2f \n",valor);
for(i=0; i < n; i++) valor += valor*taxa;
printf("valor final: %7.2f \n",valor);
}

Neste exemplo, no comando printf, o especificador de formato "%7.2f" está sendo usado
para formatar um valor do tipo float, ocupando um campo de 7 caracteres, com duas
casas após o ponto decimal.

#include <stdio.h>

int main()
{
char x;
for(x = 'a'; x <= 'z'; x++) printf("%c",x);
printf("\n");
}
Neste exemplo, o operando ++ está sendo aplicado a uma variável do tipo char. O
resultado dessa operação é o "caracter seguinte" na sequência de caracteres da
máquina.
Ainda neste exemplo, a sequência o especificador de formato "%c" está sendo usado
para indicar que a variável correspondente será escrita como um caracter.

Funções
Funções em C permitem agrupar uma sequência de operações sob um nome através do qual é
possível executar essa sequência. Exemplo:
...
int max(int i, int j)
{
if (i > j) return i;
else return j;
}
...
O exemplo acima mostra a definição da função max, que ao ser executada retorna um
valor do tipo int. Os comandos entre '{' e '}' correspondem ao corpo da função, que é
executado toda vez que a função for ativada (ou chamada).
As variáveis i e j, declaradas entre parentesis, são os parâmetros da função. Estes são
utilizados pelo programa que usa a função para "passar" os valores a serem usados pela
função ao realizar os seus cálculos.
Para chamar uma função num programa, usa-se o nome da mesma, seguido dos valores
que devem ser associados aos parâmetros, entre parêntesis. Exemplos:
...
int main()
{
int x,y,z, m;
scanf(" %d %d %d",x,y,z);
m = max(x,y);
m = max(m,z);
printf("m: %d\n",m);
}
Neste exemplo, os comando "m = max(x,y);" é usado para chamar a função max,
passando como valores para i e j o valor das variáveis x e y. O valor passado como

11
parâmetros nesse caso poderia ser qualquer valor, definido por uma constante, uma
variável, ou uma expressão. Uma chamada válida poderia ser "max(10,x+y);" (se isso fizer
sentido no programa sendo escrito).
A chamada à função "max" retorna um valor do tipo inteiro, que pode ser utilizado no
programa em qualquer situação onde um valor inteiro é válido. Por exemplo, a sequência
de comandos
m = max(x,y);
m = max(m,z);
poderia ser substituída por

m = max(max(x,y),z);
O programa do exemplo acima poderia ser reescrito de forma mais compacta como:
int main()
{
int x,y,z, m;
scanf(" %d %d %d",x,y,z);
printf("m: %d\n",max(max(x,y),z));
}
A partir da definição de uma função num programa, ela passa a estar disponível como se
fosse uma nova facilidade da linguagem, como se a mesma pudesse ser "extendida" em
função das necessidades de uma aplicação. Esse é um recurso poderoso e que aparece
em praticamente todas as linguagens de programação.
É possível também utilizar funções definidas em módulos externos, combináveis com o
programa. É exatamente isso que acontece com as funções utilizadas até agora para
fazer entrada e saída, printf e scanf: essas funções estão definidas na biblioteca de
funções stdio.h.
Outro exemplo
A função abaixo calcula o máximo divisor comum entre dois inteiros positivos:

int mdc(int a, int b)


{
while(a != b)
if (a > b) a -=b; else b -= a;
return a;
}
O comando return
O comando return interrompe a execução da função e indica o valor de retorno da
mesma. A execução do programa chamador continua a partir do ponto onde foi feita a
chamada à função.
O tipo de retorno
No exemplo acima, o valor de retorno da função mdc é do tipo inteiro. Na verdade
qualquer um dos tipos primitivos da linguagem (int, char e float) podem ser usados como
valor de retorno de uma função.
Em alguns casos, uma função não necessita retornar um valor. Nesse caso é possível
declarar a função como void, indicando que a mesma não retorna um valor. Um exemplo:
void cabecalho()
{
printf("==================================\n");
printf(" Título \n");
printf("==================================\n");
}

12
As funções getchar e putchar
As funções getchar e putchar, definidas na biblioteca stdio são orientadas à leitura e
escrita de caracteres. Na sua forma mais simples, elas leem e escrevem caracteres pela
entrada e saída padrão. O exemplo a seguir mostra o seu uso:

/* cópia da entrada padrão p/ saída padrão */


#include <stdio.h>
int main()
{
int c;

c = getchar(); /* le um caracter */

while (c != EOF) /* EOF delimita "fim de arquivo" */


/* (definido em stdio.h) */
{
putchar(c);
c = getchar()
}
}
A função getchar() devolve o próximo caracter lido. A função putchar() escreve o caracter
passado como parâmetro (não devolve um valor). O mesmo programa pode ser escrito de
forma mais concisa tirando vantagem do fato de que um comando em C é uma
expressão. No caso do comando de atribuição "c = getchar()", o valor da expressão é o
valor atribuido à variável c:

/* cópia da entrada padrão p/ saída padrão */


#include<stdio.h>
int main()
{
int c;
while ((c = getchar()) != EOF) putchar(c);
}

Outro exemplo
O programa abaixo conta o número de linhas do texto lido a partir da entrada padrão:

/* conta o número de linhas da entrada padrão */


#include <stdio.h>
int main()
{
int c, nl;
nl = 0;
while((c = getchar()) != EOF)
if ( c == '\n') ++nl; /* '\n' = fim de linha */
printf("número de linhas: %d\n", nl);
}

13
int main() ?
Nos exemplos mostrados até aqui, o programa principal, é declarado sempre como
...
int main() { ... }
...
Essa declaração segue o mesmo padrão usado na declaração de uma função. Na
verdade, trata-se realmente de uma função. O UNIX inicia a execução do programa a
partir da função cujo nome é main.
Essa é uma convenção adotada pelo UNIX e usada por outros sistemas operacionais
(uma exceção é o Windows no qual a execução do programa se inicia a partir de uma
função chamada WinMain()).
A função main pode ou não retornar um valor. Sua declaração poderia ser da forma

void main() { ... } ou ainda


main() { ... }
O valor eventualmente retornado pela função main pode ser utilizado pela shell.
Pelo fato de ser uma função, main ainda pode ter parâmetros. Isso será visto mais
adiante.
Variáveis locais e globais
No exemplo abaixo, as variáveis x, y, z e m são declaradas "dentro" da função main e só
são disponíveis ou visíveis pelos comandos que compõem a função onde foram
declaradas. Isso vale para qualquer função: as variáveis declaradas numa função só são
visíveis dentro dessa função.

int main()
{
int x,y,z, m;
scanf(" %d %d %d",x,y,z);
m = max(x,y);
m = max(m,z);
printf("m: %d\n",m);
}
Se duas funções declaram variáveis com nomes iguais, como cada declaração é local a
cada uma das funções, essas variáveis são na verdade duas variáveis independentes,
que por acaso têm o mesmo nome. Exemplo:

#include <stdio.h>
int f(int n)
{
int i,s;
s = 0;
for(i=1; i<=n; i++) s += i;
return s;
}

int g(int n)
{
int i,p;
p = 1;
for(i=1; i <=n; i++) p *= i;
return p;
}
14
int main()
{
...
int i,p,s;
...
}
Assim como as variáveis locais, os parâmetros de uma função são locais à mesma.
Uma variável global é uma variável declarada "fora" de uma função e pode ser utilizada
por qualquer função do programa. Um exemplo:

#include <stdio.h>

#define NMAX 10

/* as variáveis tSize e tab são globais */


int tSize;
int tab[NMAX];

void init() { tSize = 0; }

int insert(int v)
{
if(tSize >= NMAX-1) return -1;
tab[++tSize] = v;
return tSize;
}

int sort()
{
int i,j,t;
for(i=0; i < tSize-1; i++)
for(j = i+1; j < tSize; j++)
if(tab[i] > tab[j])
{
t = tab[i]; tab[i] = tab[j]; tab[j] = t;
}
}

void printTab()
{
int i;
printf("tab: ");
for(i=0; i < tSize; i++) printf("%d ",tab[i]);
printf("\n");
}

int main()
{
init();
insert(5); insert(8); insert(2); insert(12);
sort();

15
printTab();
}
Passagem de Parâmetros
Os exemplos de funções mostrados até agora, definem um conjunto de parâmetros que
têm um dos tipos primitivos da linguagem (int, char, float, double ). Um exemplo:
...
float max(float a, float b)
{
if(a > b) return a; else return b;
}
...
Ao se chamar essa função, os valores de cada um dos parâmetros efetivos serão
associados aos parâmetros formais a e b. Exemplos:
...
x = max(10.0, z-4.3);
p = max(r,s);
w = max(10.0,max(x,p));
...
No primeiro exemplo, o valor 10.0 é associado ao parâmetro formal a e o valor da
expressão "z-4.3" é associado ao parâmtro b. Esse tipo de passagem de parâmetros é
chamado de passagem por valor, e é a forma básica de passagem de parâmetros em C.
A passagem de parâmetros por valor é aplicável à maioria das situações de programação.
No entanto existem casos em que é necessário extende-la. Suponhamos por exemplo
que um programa necessite com frequência trocar o valor de duas variáveis e que que a
mesma deverá ser aplicada a diferentes pares de variáveis ao longo do programa. Se
implementarmos essa função da forma como mostrada abaixo, ela não apresentará a
funcionalidade desejada:

void troca(int a, int b)


{
int t;
t = a; a = b; b = t;
}
Essa função opera com os valores dos parâmetros, que contém a cópia dos valores que
lhes foram passados como parâmetros efetivos. A troca portanto ocorre entre os
parâmetros, que nada mais são que variáveis locais à função.
Referências
Em C é possível declarar uma variável (ou um parâmetro) como sendo uma referência ou
apontador para um determinado tipo. Um exemplo:

int *p;
Essa declaração define a variável p como uma referência a um inteiro (que pode ser uma
outra variável). Se quisermos, por exemplo atribuir um valor à variável referenciada por p,
podemos fazer o seguinte:

*p = 10;
ou ainda, para usar o valor da variável referenciada por p numa expressão

x = *p + 10;
O operador de referência &
Para que variáveis do tipo referência como p usada nos exemplos acima tenham alguma
utilidade, é necessário que a linguagem permita que se indique que "p referencia uma

16
certa variável". O operador '&' serve justamente para esse propósito: se x é uma variável
qualquer, &x é a referência a essa variável. Um exemplo:
...
int x = 1;
int *p;
...
p = &x; /* o valor de p e uma referência a x */
*p = 10;
printf("valor de x: %d\n",x);
..
Neste exemplo, a o comando "p = &x;" faz com que p passe a "referenciar" ou "apontar" para a variável x.
Isso significa que "*p" (ou seja, "a variável referenciada por p" passa a ser x. Qualquer alteração em *p é
equivalente a uma alteração em x (e vice-versa, obviamente). O valor escrito pelo comando "printf" será
portanto "10".
Uso de referências em parâmetros
O tipo referência pode ser usado nos parâmetros de uma função. Por exemplo, a função
"troca" pode ter o efeito desejado se utilizarmos os parâmetros de forma adequada:

void troca(int *p, int *q)


{
int t;
t = *p;
*p = *q;
*q = t;
}
Essa nova versão da função, pode ser utilizada em diversas situações. É importante notar
que os parâmetros efetivos devem ser referências a variáveis.
...
int a,b;
int v[10] = {0, 1, 3, 2, 4, 5, 6, 7, 8, 9}
...
a = 2; b = 5;
troca(&a,&b);
...
troca(&v[2],&v[3]);
...
Parâmetros do tipo referência são utilizáveis sempre que se deseja que a função altere o valor do
parâmetro e que essa alteração se aplique ao parâmetro efetivo. O operador '&' só é aplicável a
variáveis. Não faz sentido aplicá-lo a uma expressão.
Vetores como parâmetro
Quando declaramos um vetor em C, a variável correspondente a esse vetor é uma
referência à região de memória onde o mesmo é armazenado. Ao aplicarmos um índice a
esse vetor, estamos é que estamos nos referindo a um elemento. Na verdade C trata a
indexão como um operador semelhante ao operador '*'.
O uso de um vetor como parâmetro formal de uma função tem o mesmo efeito que uma
referência: se a função alterar um elemento do vetor, essa alteração irá aparecer no
parâmetro efetivo. Exemplos:
...
void ordena(int v[],int n)
{
int i,k;
do {

17
k = 0;
for(i=0; i < n-1; i++)
if(v[i] > v[i+1])
{
troca(&v[i],&v[i+1]); k++);
}
} while(k!=0);
}
No exemplo acima, "v[]" denota um vetor, cujo tamanho não é fixado na função, já que o
mesmo depende do parâmetro efetivo. O segundo parâmetro, "n" indica o tamanho do
parâmetro efetivo e deve ser preenchido ao se chamar a função. O exemplo abaixo
mostra alguns usos da função "ordena".

...
int a[10], m[12][31];
...
ordena(a,10);
ordena(m[5],31);
...

Compilação e execução de um programa


Para que um programa escrito em C possa ser executado sob o UNIX a partir da shell é
necessário o seguinte:
• criação de um arquivo texto contendo o programa fonte em C
• Compilação do programa gerando o programa executável correspondente
• Ativação do programa executável através da shell
Criação do programa fonte
O programa fonte em C pode ser feita através de um dos vários editores de texto
disponíveis: emacs, vi, pico, kate, gedit. O programa fonte pode até mesmo ser criado
através do comando cat da shell.
Compilação através do compilador gcc
O compilador gcc é uma versão open source do compilador C do UNIX, chamdo cc ("C
compiler"). Ele é responsável por traduzir o programa fonte, na forma de um arquivo texto,
para o programa executável (em linguagem de máquina).
A sua forma básica de uso é a seguinte:

gcc prog.c
Esse comando, causa a tradução do programa fonte em C contido no arquivo "prog.c"
para a linguagem de máquina. O programa executável gerado, neste caso, vai estar num
arquivo chamado "a.out". Esse é o nome padrão para a saída do compilador.
Caso o programa fonte contenha erros de compilação, estes serão indicados na saída
padrão (de forma nem sempre amigável). Para a correção dos erros, usa-se novamente o
editor de textos.
O nome "a.out" nem sempre é o mais conveniente para um programa executável. Além
disso, pelo fato de ser sempre o mesmo, o conteúdo anterior desse arquivo é destruído a
cada compilação. Uma saída é renomear o arquivo após cada compilação (p. ex. "mv
a.out prog"). Outra possibilidade mais interessante é usar uma opção de compilação
indicando o nome desejado para o progrma executável. Isso é feito através da opção "-o
nome". Exemplo

18
gcc -o prog prog.c
Ativação do programa
A ativação do programa a partir da shell é feita da mesma forma que a ativação dos
comandos padrão do UNIX (estes, na verdade, são programas executáveis como
qualquer outro).

Strings
Quando escrevemos uma cadeia de caracteres ("string") num programa, a mesma é
compatível com os tipos "char *" e "char[]". Exemplo:

#include <stdio.h>
int main()
{
char * texto = "Um título";
char nome[] = "João da Silva";
char *dias[7] = {
"segunda","terça", "quarta",
"quinta", "sexta", "sábado",
"domingo"
};
int i;

printf("%s\n",texto);
printf("%s\n",nome);
for(i=0; i < 7; i++) printf(" %s ",dias[i]); printf("\n");
}
No exemplo acima,
• texto é uma referência a um string, que aponta para o string "Um título"
• nome é um vetor de caracteres, cujo tamanho é determinado a partir do valor
atribuído a ele ("João da Silva");
• dias é um vetor de 7 apontadores para caracteres.
Em qualquer um dos casos, os strings são representados como uma sequência de
caracteres delimitada pelo caracter "null", que é o caracter cuja representação interna é
igual a zero. A função abaixo usa essa propriedade de um string para determinar o seu
tamanho.
int tamanho(char s[])
{
int i;
for(i=0; s[i] != 0; i++);
return i;
}
Strings constituem um recurso importante em programação e as bibliotecas padrão de C
oferecem um extenso conjunto de funções para sua manipulação. Algumas dessas
funções:
• int strlen(char * str) - devolve o tamanho de um string
• char *strcpy(char *dest, char *origem) - copia um string
• char *strcat(char *dest, char *origem) - concatena 2 strings
• char *strcmp(char *str1, char *str2) - compara 2 strings

19

Você também pode gostar