Se você está interessado em aprender a linguagem C, saiba que você fez uma ótima escolha. Essa linguagem está presente em todos os sistemas operacionais conhecidos atualmente. Um sistema linux, por exemplo, tem o seu kernel e sua base toda construída em linguagem C.
A linguagem C é uma linguagem de alto e baixo nível, o que significa que você pode usá-la para criar kernels, drivers, ou até mesmo sistemas operacionais completo. É possível também usar essa linguagem até mesmo para construir partes de websites, como sistemas bancários que requerem uma camada de segurança maior.
Enfim, aprender a linguagem C é necessário para qualquer programador, principalmente para usuários de sistemas linux que desejam aprender sobre o kernel, ou queiram criar seus próprios drivers, módulos e ferramentas de linha de comando.
Apesar de ser uma linguagem mais utilizada para desenvolvimento de coisas complexas, a linguagem C é a linguagem mais simples que existe, possuindo poucas palavras chaves e uma sintaxe completamente simples. Outras linguagens de programação, como PHP, JavaScript e C++, possuem uma sintaxe derivada da linguagem C. Isso significa que aprendendo a linguagem C você também aprende um pouco de outras linguagens.
Nesse artigo vou lhe apresentar a linguagem C de forma prática para que você já possa começar a criar e compilar seus primeiros algoritmos. Um dos requisítos para você seguir esse tutorial é que você tenha conhecimento de lógica de programação. Nesse artigo não estarei ensinando lógica de programação. O foco aqui é detalhar a linguagem C em geral.
Antes de começar
Antes de começar a estudar o conteúdo desse artigo tenha em mãos um bloco de nota para escrever seus algoritmos e um compilador para testá-los. Se você está usando o windows, você pode instalar o Notepad++ para escrever seus códigos e o Mingw para compilá-los. Notepad++ é um excelente editor de textos para programação.
Se você utiliza alguma distribuição linux então você pode usar o geany para escrever seus algoritmos e, para compilação você pode usar o gcc. Você pode instalar essas ferramentas usando o gerenciador de pacotes da sua distribuição.
A estrutura de um programa
Na linguagem C precisamos iniciar nosso programa dentro de uma função base, a qual é chamada na execução do programa, e que recebe os argumentos iniciais passados ao programa. Todo programa em C precisa dessa função para ser iniciado, exceto as bibliotecas. A definição dessa função é um padrão que deve ser seguido para que seu programa possa ser iniciado corretamente.
int main(int argc, char **argv) {
//função principal
}
Acima definimos a função principal declarando as duas variáveis necessárias para recebermos os argumentos que são passados ao programa na sua execução inicial. Ao executarmos esse programa, seja diretamente ou indiretamente por outro programa, podemos passar todos os argumentos necessários para a função main.
O primeiro argumento (int argc) precisa ser um número inteiro que contabiliza o número de argumentos passados a função. O segundo argumento (char **argv) precisa ser uma lista de argumentos. O primeiro elemento dessa lista é sempre o nome do próprio programa. Em argv[0] sempre estará o nome do programa, e argc será sempre 1 quando o programa não receber argumentos.
Você pode compilar o código abaixo e executá-lo sem argumento algum para analisar o conteúdo de argc e argv.
#include <stdio.h>
int main(int argc, char **argv) {
printf("argc: %d\n", argc);
printf("argv[0]: %s\n", argv[0]);
return 0;
}
Ao executar um programa na linha de comando os argumentos da função main devem ser passados juntamente com a execução do programa:
./programa argumento1 argumento2 argumento3
No caso acima a variável argc terá o valor 4, pois são três argumentos mais o nome do programa. Já em argv teremos quatro itens, sendo o item zero o nome do programa.
argc: 4
argv[0]: ./programa
argv[1]: argumento1
argv[2]: argumento2
argv[3]: argumento3
O algoritmo abaixo mostra todos os argumentos passados para a função main.
#include <stdio.h>
int main(int argc, char **argv) {
printf("argc: %d\n", argc);
for (int i = 0; i < argc; i++)
printf("argv[%d]: %s\n", i, argv[i]);
return 0;
}
Um programa em C também requer a importação de bibliotecas, pois são nessas bibliotecas que estão as funções que utilizaremos para criar nosso programa. A linguagem C possui algumas bibliotecas padrão, mas o seu programa não precisa se limitar a elas. Você pode importar qualquer biblioteca necessária por seu programa, e você também pode criar suas próprias bibliotecas.
A importação de bibliotecas precisa ser realizada no início do programa, antes da função main. Nós apenas importamos as declarações das funções, e não o código delas. O código das bibliotecas, que são arquivos compilados, é colocado ao nosso programa somente durante a compilação.
Para importar uma biblioteca usamos a palavra-chave #include:
#include <stdio.h> //importa funções para entrada e saída de dados
#include <strings.h> //importa funções para uso com strings
Então a estrutura de um programa em C fica assim:
//bibliotecas
#include <stdio.h>
//função principal
int main (int argc, char **argv) {
printf("Hello World!");
}
Compilando um programa
Agora que você já aprendeu um pouco sobre a linguagem C e sua estrutura básica, está na hora de aprender a compilar os algoritmos.
Algoritmos da linguagem C são salvos em arquivos com a extensão “.c“. Sempre que você escrever um programa em C você deve salvá-lo com essa extensão para que o compilador possa compreender que o arquivo se trata de um algoritmo da linguagem C.
Para compilar um programa precisamos informar o arquivo .c e um nome para o programa depois de compilado.
compilador <algoritmo.c> <nome do programa>
Exemplo:
gcc programa.c meuprograma
No caso acima, o algoritmo que está no arquivo “programa.c” será compilado, resultando no arquivo meuprograma, que é o programa compilado. Em sistemas linux não haverá extensão no final do nome do programa. Somente no windows é que o programa receberá a extensão “.exe” no final do nome.
Para executar o programa podemos abrir um terminal no linux ou um cmd no windows e informar o nome do programa.
No linux:
./meuprograma argumentos
No windows:
meuprograma.exe argumentos
Palavras chaves
As palavras chaves ou palavras reservadas são aquelas que não podem ser usadas para definir nome de funções ou tipos de dados. Essas palavras são reservadas pela linguagem, e seu uso é destinado para a escrita dos algoritmos. São essas palavras que denominam o termo “linguagem de programação”. Cada linguagem de programação possui suas palavras reservadas.
A linguagem C possui poucas palavras reservadas, que podem ser facilmente decoradas. Abaixo segue algumas palavras chaves com sua descrição. Não se preocupe em querer memorizar tudo agora. Com o tempo você memoriza sem muito esforços.
- include: usada para importar cabeçalhos de bibliotecas
- int: define o tipo inteiro
- char: define o tipo caracter
- float: define o tipo número com casa decimal
- double: número com casas decimais com maior precisão
- struct: define estrutura de dados
- enum: define uma lista enumerada
- void: tipo de dados genérico
- unsigned: tipo de dados sem sinal
- return: retorno de uma função
- * (asterísco): define ponteiros
- stdin: ponteiro para entrada de dados
- stdout: ponteiro para saída de dados
- stderr: ponteiro para saída de erros
- EOF: marca o fim de um arquivo
- goto: usada para saltar para outras partes do programa
- FILE *: declara um ponteiro para arquivos
- typedef: define um novo tipo de dados
- short: tipo de dados de 16 bits
- long: tipo de dados de 32 ou 64 bits
- for: cria loops com predefinições
- while: para criar loops
- if: testa uma condição
- else: usado se a condição de if for falsa
- do while: para criar loops
- extern: informa uma definição externa de uma função ou tipo de dados
Tipos de dados
Os tipos de dados na linguagem C são de baixo nível. As informações das variáveis são carregadas e armazenadas diretamente na memoria RAM pelo programador, sem mediação por parte da linguagem, como ocorre no caso de linguagens interpretadas.
É preciso estar atento as definições e uso dos tipos de dados na linguagem C, pois um erro pode tornar um software vunerável a ataques de hacker’s. Buffer overflow é um famoso tipo de ataque que explora falhas causadas pelo mal uso do tipo caracter (char).
Na linguagem C o programador tem controle total sobre cada bit da informação armazenada em variáveis. Uma string por exemplo, deve ter seus caracteres copiados separadamente, sendo um por um. Na linguagem C uma string é uma cadeia de caracteres armazenados em sequência na memória RAM. Cada caracter da string deve ser armazenado separadamente em um índice de um array do tipo char.
Definindo uma variável do tipo string:
char nome[32];
Em linguagem C não temos o tipo string, então devemos usar a palavra char para definir um tipo string. Um tipo string possui vários caracteres, então devemos declarar um array do tipo char.
Armazenando dados na variável do tipo string:
strncpy(nome, "Maria da Silva", 14);
Como citado anteriormente, cada caracter deve ser copiado separadamente, então para escrevermos dados em um array do tipo char devemos usar uma função para agilizarmos o processo. A função strncpy é nada mais do que um loop usado para percorrer todos os caracteres da string “Maria da Silva”, e fazer a cópia deles para a variável nome.
Poderiamos criar nossa própria função strncpy dessa forma:
int strncpy(char *destino, const char* string, int total) {
for (int i = 0; i < total && string[i] != '0'; i++) {
destino[i] = string[i];
}
return i;
}
Acima usamos o tipo char para armazenar uma cadeia de caracteres, porém podemos usar o tipo char para armazenar apenas um caracter. O tipo char armazena uma informação de 8 bits, isto é, 1 byte. Ao armazenarmos um caracter estamos apenas salvando seu valor numérico na memória RAM. Por ser um tipo de 8 bits, o tipo char pode armazenar até 256 informações diferentes, sendo de 0 a 255, ou de -128 a 128.
Definindo um tipo char:
char genero;
Armazenando dados em um tipo char:
genero = 'm';
Se consultarmos a tabela ASCII, veremos que o caracter “m” corresponde ao número 109, logo o valor da variável “genero” é nada mais do que o número 109, o que faz a condição abaixo ser verdadeira.
if (genero == 109) {
//é masculino
} else {
//é feminino
}
continua…