Edição das 13h02min de 26 de novembro de 2007
Predefinição:Info/Linguagem de computador C é uma linguagem de programação de propósito geral, estruturada, imperativa, procedural, de baixo nível[1] e padronizada, criada em 1972, por Dennis Ritchie, nos laboratórios Bell, para ser usada no sistema operacional UNIX. Desde então, espalhou-se por muitos outros sistemas operativos, e tornou-se uma das linguagens de programação mais usadas.
C tem como ponto forte, a sua eficiência, e é a linguagem de programação preferida para o desenvolvimento de sistemas e softwares de base, apesar de também ser usada para desenvolver programas de computador. É também muito usada no ensino de ciências da computação, mesmo não tendo sido projetada para estudantes e apresentando algumas dificuldades no seu uso. Outra característica importante de C, é sua proximidade do código de máquina, que permite que um projetista seja capaz de fazer algumas previsões de como o software irá se comportar, ao ser executado.
C tem como ponto fraco, a falta de proteção que dá ao programador. Praticamente tudo que se expressa em um programa em C, pode ser executado, como por exemplo, pedir o vigésimo membro de um vetor com apenas dez membros. Os resultados são muitas vezes totalmente inesperados, e os erros, difíceis de encontrar.
Muitas linguagens de programação foram influenciadas por C, sendo que a mais utilizada atualmente é C++, que por sua vez foi uma das inspirações para Java.
História
Desenvolvimentos iniciais
O desenvolvimento inicial de C, ocorreu nos laboratórios Bell da AT&T, entre 1969 e 1973. Segundo Ritchie, o período mais criativo ocorreu em 1972. Deu-se o nome "C" à linguagem porque muitas das suas características derivaram de uma linguagem de programação anterior chamada "B". Há vários relatos que se referem à origem do nome "B": Ken Thompson dá crédito à linguagem de programação BCPL mas ele também criou uma outra linguagem de programação chamada 'Bon, em honra da sua mulher Bonnie. Por volta de 1973, a linguagem C tinha se tornado suficientemente poderosa para que grande parte do núcleo de UNIX, originalmente escrito na linguagem de programação PDP-11/20 assembly, fosse reescrito em C. Este foi um dos primeiros núcleos de sistema operativo que foi implementado numa linguagem sem ser o assembly, sendo exemplos anteriores o sistema Multics (escrito em PL/I) e TRIPOS (escrito em BCPL).
C de K&R
Em 1978, Dennis Ritchie e Brian Kernighan publicaram a primeira edição do livro The C Programming Language. Esse livro, conhecido pelos programadores de C como "K&R", serviu durante muitos anos como uma especificação informal da linguagem. A versão da linguagem C que ele descreve é usualmente referida como "C de K&R" (a segunda edição do livro cobre o posterior padrão ANSI C, descrito abaixo). K&R introduziram as seguintes características na linguagem:
- tipos de dados
struct
- tipos de dados
long int
- tipos de dados
unsigned int
- O operador =+ foi alterado para +=, e assim sucessivamente (o análise léxica do compilador confundia o operador =+. Por exemplo, i =+ 10 e i = +10).
C de K&R é frequentemente considerado a parte mais básica da linguagem cujo suporte deve ser assegurado por um compilador C. Durante muitos anos, mesmo após a introdução do padrão C ANSI, ele era considerado o "menor denominador comum" em que programadores de C se apoiavam quando uma portabilidade máxima era desejada, já que nem todos os compiladores eram actualizados para apoiar na íntegra o padrão C ANSI, e código C de K&R razoavelmente bem escrito é também legal em C ANSI. Nos anos que se seguiram à publicação do C K&R, algumas características "não-oficiais" foram adicionadas à linguagem, suportadas por compiladores da AT&T e de outros vendedores. Estas incluíam:
- funções
void
e tipos de dadosvoid *
- funções que retornam tipos
struct
ouunion
- campos de nome
struct
num espaço de nome separado para cada tipostruct
- atribuição a tipos de dados
struct
- qualificadores
const
para criar um objecto só de leitura - uma biblioteca-padrão que incorpora grande parte da funcionalidade implementada por vários vendedores
- enumerações
- cálculos de ponto-flutuante em precisão simples (no C K&R, os cálculos intermediários eram feitos sempre em double, porque era mais eficiente na máquina onde a primeira implementação do C foi feita)
C ANSI e C ISO
Durante os finais da década de 1970, a linguagem C começou a substituir a linguagem BASIC como a linguagem de programação de microcomputadores mais usada. Durante a década de 1980, foi adoptada para uso no PC IBM, e a sua popularidade começou a aumentar significativamente. Ao mesmo tempo, Bjarne Stroustrup, juntamente com outros nos laboratórios Bell, começou a trabalhar num projecto onde se adicionavam construções de linguagens de programação orientada por objectos à linguagem C. A linguagem que eles produziram, chamada C++, é nos dias de hoje a linguagem de programação de aplicações mais comum no sistema operativo Windows da companhia Microsoft; C permanece mais popular no mundo UNIX. Em 1983, o instituto norte-americano de padrões (ANSI) formou um comité, X3j11, para estabelecer uma especificação do padrão da linguagem C. Após um processo longo e árduo, o padrão foi completo em 1989 e ratificado como ANSI X3.159-1989 "Programming Language C". Esta versão da linguagem é freqüentemente referida como C ANSI. Em 1990, o padrão C ANSI, após sofrer umas modificações menores, foi adotado pela Organização Internacional de Padrões (ISO) como ISO/IEC 9899:1990. Um dos objetivos do processo de padronização C ANSI foi o de produzir um sobreconjunto do C K&R, incorporando muitas das características não-oficiais subseqüentemente introduzidas. Entretanto, muitos programas tinham sido escritos e que não compilavam em certas plataformas, ou com um certo compilador, devido ao uso de bibliotecas de funções não-padrão e ao fato de alguns compiladores não aderirem ao C ANSI.
C99
Após o processo ANSI de padronização, as especificações da linguagem C permaneceram relativamente estáticas por algum tempo, enquanto que a linguagem C++ continuou a evoluir. (em 1995, a Normative Amendment 1 criou uma versão nova da linguagem C mas esta versão raramente é tida em conta.) Contudo, o padrão foi submetido a uma revisão nos finais da década de 1990, levando à publicação da norma ISO 9899:1999 em 1999. Este padrão é geralmente referido como "C99". O padrão foi adoptado como um padrão ANSI em Março de 2000. As novas características do C99 incluem:
- funções em linha
- remoção de restrições sobre a localização da declaração de variáveis (como em C++)
- adição de vários tipos de dados novos, incluindo o
long long int
(para minimizar problemas na transição de 32-bits para 64-bits), um tipo de dados boolean explicito (chamado _Bool) e um tipocomplex
que representa números complexos - vetores de dados de comprimento variável (o vetor pode ter um tamanho diferente a cada execução de uma função, mas não cresce depois de criado)
- suporte oficial para comentários de uma linha iniciados por
//
, emprestados da linguagem C++ - várias funções de biblioteca novas, tais como
snprintf()
- vários ficheiros-cabeçalho novos, tais como
stdint.h
O interesse em suportar as características novas de C99 parece depender muito das entidades. Apesar do GCC e vários outros compiladores suportarem grande parte das novas características do C99, os compiladores mantidos pela Microsoft e pela Borland suportam pouquíssimos recursos do C99, e estas duas companhias não parecem estar muito interessadas em adicionar tais funcionalidades, ignorando por completo as normas internacionais. A Microsoft parece preferir dar mais ênfase ao C++ [1]
Visão geral
C é uma linguagem imperativa e procedural, para implementação de sistemas. Seus pontos de design foram para ele ser compilado, fornecendo acesso de baixo nível à memória e baixos requerimentos do hardware. Também foi desenvolvido para ser uma linguagem de alto nível, para maior reaproveitamento do código. C foi útil para muitas aplicações que forma codificadas originalmente em Assembly.
Essa propriedade não foi acidental; a linguagem C foi criada com o objectivo principal em mente: facilitar a criação de programas extensos com menos erros, recorrendo ao paradigma da programação algorítmica ou procedimental, mas sobrecarregando menos o autor do compilador, cujo trabalho complica-se ao ter de realizar as características complexas da linguagem. Para este fim, a linguagem C possui as seguintes características:
- Uma linguagem nuclear extremamente simples, com funcionalidades não-essenciais, tais como funções matemáticas ou manuseamento de ficheiros (arquivos), fornecida por um conjunto de bibliotecas de rotinas padronizada;
- A focalização no paradigma de programação procedimental;
- Um sistema de tipos simples que evita várias operações que não fazem sentido
- Uso de uma linguagem de pré-processamento, o pré-processador de C, para tarefas tais como a definição de macros e a inclusão de múltiplos ficheiros de código fonte;
- Um acesso de baixo-nível à memória do computador, através do uso de ponteiros;
- Parâmetros que são sempre passados por valor para as funções e nunca por referência (É possível simular a passagem por referência com o uso de ponteiros);
- Definição do alcance lexical de variáveis;
- Estruturas de variáveis, (structs), que permitem que dados relacionados sejam combinados e manipulados como um todo.
Algumas características úteis, que faltam em C, podem ser encontradas em outras linguagens, que incluem:
- Segurança de tipo;
- Coletor de lixo (mais encontrado em linguagens interpretadas);
- Vetores que crescem automaticamete;
- Classes ou objectos com comportamento (ver orientação a objetos);
- Um sistema avançado de sistema de tipos;
- Closures;
- Funções aninhadas;
- Programação genérica;
- Sobrecarga de operadores;
- Meta-programação;
- Apoio nativo de multithreading e comunicação por rede.
Apesar da lista de características úteis que C não possui ser longa, isso não tem sido um impedimento à sua aceitação, pois isso permite que novos compiladores de C sejam escritos rapidamente para novas plataformas, e também permite que o programador permaneça sempre em controle do que o programa está a fazer. Isto é o que por várias vezes permite o código de C correr de uma forma mais eficiente que muitas outras linguagens. Tipicamente, só código de assembly "afinado à mão" é que corre mais rapidamente, pois possui um controle completo da máquina, mas avanços na área de compiladores juntamente com uma nova complexidade nos processadores modernos permitiram que a diferença tenha sido rapidamente eliminada. Uma consequência da aceitação geral da linguagem C é que frequentemente os compiladores, bibliotecas e até intérpretes de outras linguagens de nível maior sejam eles próprios implementados em C.
Tipos de dados
A linguagem C tem um sistema de tipos semelhante ao de alguns descendentes da linguagem ALGOL, tais como Pascal. Possui tipos para números inteiros de vários tamanhos com e sem sinal, números de ponto flutuante, caracteres e estruturas (struct
s).
C usa extensivamente ponteiros, um tipo muito simples de referência que guarda o endereço de memória da variável. O ponteiro pode ser desreferenciado, uma operação que busca o objecto que se encontra na morada da memória que o ponteiro possui, morada essa que pode ser manipulada através de aritmética de ponteiros. Durante o tempo de execução, o ponteiro é simplesmente uma morada de máquina tais como aquelas manipuladas em assembly, mas em tempo de compilação possui um tipo complexo que indica o tipo do objecto para onde ele aponta, permitindo que se verifique o tipo de expressões, incluindo ponteiros. Os ponteiros são usados extensivamente em C. O tipo linha de texto de C é simplesmente um ponteiro para uma matriz de caracteres e alocação dinâmica de memória, descrita abaixo, é efectuada através de ponteiros.
Os ponteiros em C possuem um valor reservado especial, NULL
, que indica que não estão a apontar para uma morada. O uso desse valor como morada é muito útil na construção de várias estruturas de dados, mas causa comportamento não-definido (possivelmente uma falha de sistema) ao ser desreferenciado. Um ponteiro que possui o valor NULL
é chamado ponteiro nulo. Os ponteiros são declarados (e desreferenciados) com um * (asterisco), portanto o tipo int* denota um ponteiro para número(s) inteiro(s). A linguagem C também fornece um tipo especial de ponteiros, o void*, que se traduz num ponteiro que aponta para um objecto de tipo desconhecido.
A linguagem C também tem apoio a nível de linguagem para disposições estáticas (de dimensão fixa) de tipos. As disposições de tipos podem parecer ter mais que uma dimensão apesar de serem tecnicamente disposições de disposições de tipos. Em memória, tais estruturas são posicionadas com as linhas uma depois da outra (a alternativa seria armazenar os dados em colunas, usado em outras linguagens). O acesso a disposições de tipos é feito através de ponteiros e aritmética de ponteiros; o nome da disposição é tratado como se fosse um ponteiro que aponta para o início da disposição. Em certas aplicações não é razoável usarem-se disposições de tipos de dimensão fixa e por isso a alocação dinâmica de memória pode ser usada para criar disposições de tipos de dimensão variável.
Como a linguagem C é regularmente usada em programação de baixo-nível de sistemas, há casos em que é necessário tratar um número inteiro como sendo um ponteiro, um número de ponto flutuante como sendo um número inteiro ou um tipo de ponteiro como sendo outro. Para estes casos, a linguagem C fornece a capacidade de "moldagem" (também denominado "conversão de tipo" ou casting), uma operação que, caso seja possível, força a conversão de um objecto de um tipo para outro. Apesar de ser por vezes necessário, o uso de conversões de tipo sacrifica alguma segurança oferecida pelo sistema de tipos.
- int
O tipo de dados int (inteiro) serve para armazenar valores numéricos inteiros. Existem vários tipos de inteiros, cada um de um tamanho diferente (dependendo do sistema operacional):
- int, pode possuir 16 bits, ou 32 bits, dependendo se o processador é de 16 ou 32 bits.
- short int, possui tamanho de 16 bits
- long int, possui tamanho de 32 bits
- long long int (só em compiladores C99), possui tamanho de 64 bits
Um int pode ser por padrão um long int ou um short int dependendo da implementação do compilador.
Todos estes tipos de inteiros podem ainda ser declarados precedidos da cláusula unsigned, o que faz com que só suporte números positivos. Isto faz com que, com o mesmo tamanho, uma variável suporte mais números positivos do que um signed (todos os inteiros são signed por omissão).
- char
O tipo char ocupa 1 byte, e serve para armazenar caracteres ou inteiros que caibam em um byte. Isso significa que o programa reserva um espaço de 8 bits na memória RAM do computador para armazenar um valor (bytes de tamanho maior que 8 bits são permitidos pela linguagem, mas são raros). Com vetores do tipo char é possível armazenar strings, que são cadeias de caracteres.
- float
O tipo de dados float serve para armazenar números de ponto flutuante, ou seja, com casas decimais.
- double
O tipo de dados double serve para armazenar números de ponto flutuante de dupla precisão, tem o dobro do tamanho do float e portanto o dobro da capacidade.
- struct
Em C podem ser usadas estruturas (chamados de registos em outras linguagens de programação). As estruturas são grupos de variáveis agrupadas. Uma estrutura cria um novo tipo de variáveis.
Exemplo:
#include <stdio.h> struct pessoa { unsigned short idade; char nome[51]; /* vector de 51 chars para o nome */ unsigned long bi; }; /* estrutura declarada */ int main(void) { struct pessoa Sousa={16,"Diogo Sousa",123456789}; /* declaração de uma variável tipo struct pessoa com o nome Sousa */ printf("Idade: %hu\n",Sousa.idade); printf("Nome: %s\n",Sousa.nome); printf("BI: %lu\n",Sousa.bi); return 0; }
Esta estrutura é composta por 3 elementos de tipos diferentes. Depois de ser declarada uma variável do tipo struct x, onde x é o nome da estrutura (neste exemplo Sousa), para se acessar os diversos elementos deve-se fazer x.elemento
Relações com C++
A linguagem de programação C++ foi originalmente derivada do C para suportar programação orientada a objetos. À medida que as linguagens C e C++ foram evoluindo independentemente, a divisão entre as duas veio a aumentar. O padrão C99 criou um número de características que entram em conflito. Hoje, as principais diferenças entre as duas linguagens são:
inline
- em C++, funções em linha encontram-se no espaço global enquanto que em C encontram-se no espaço do ficheiro. Por outras palavras, isso significa que, em C++, qualquer definição de qualquer função em linha (sem ser a respeito da sobrecarga de funções de C++) tem de estar em conformidade com a "regra de uma definição" da linguagem C++. Mas em C, a mesma função em linha pode ser definida de maneira diferente em diferentes ficheiros.- A palavra-chave
bool
, igual à usada em C++, em C99 necessita que se inclua o ficheiro-cabeçalho<stdbool.h>
(_Bool está sempre disponível). Padrões anteriores de C não definiam um tipo booleano e vários (e incompatíveis) métodos foram usados para simular um tipo booleano.
Algumas características originalmente desenvolvidas em C++ também apareceram em C. Entre elas encontram-se:
- protótipos de função (com declaração de tipos de parâmetros) e remoção do "int" implícito.
- comentários de linha, indicados por
//
; comentários de linha terminam com um carácter de nova-linha - a palavra-chave
inline
- tipagem mais forte
Exemplos
Olá Mundo!
A seguinte aplicação foi publicada na primeira edição de C de K&R, e tornou-se no programa de introdução padrão da maior parte dos livros sobre C. O programa envia o texto "Olá Mundo!" para a saída padrão, que é normalmente o ecrã (ou tela), mas que também pode ser um ficheiro (ou arquivo), um outro dispositivo qualquer, ou até mesmo um bit bucket, dependendo de como a saída-padrão é mapeada na altura em que o programa é executado.
int main() { printf("Olá Mundo!\n"); return 0; }
Apesar do programa acima correr correctamente, presentemente origina algumas mensagens de aviso quando compilado com C ANSI. Essas mensagens podem ser eliminadas efectuando umas pequenas alterações no programa original:
#include <stdio.h> /* Pacotes com funções de entrada e saída */ int main(void) { printf("Olá, Mundo!\n"); return 0; }
A primeira linha do programa é uma directiva de pré-processamento #include, que causa que o compilador substitua aquela linha pela totalidade do conteúdo do ficheiro (ou outra entidade) a que a directiva se refere. Neste caso o ficheiro padrão stdio.h
(que contém protótipos de funções para trabalho com entrada e saída padrão) irá substituir a linha. Os caracteres < >
indicam que o ficheiro stdio.h encontra-se no local em que, quando da configuração do compilador, se definiu como padrão para localização dos ficheiros de inclusão (header files, geralmente com a extensão .h).
A linha (não-vazia) seguinte indica que uma função denominada "main" está a ser definida. A função "main" tem um significado especial nos programas de C, pois é a função que é corrida de início quando o programa começa . os caracteres {}
delimitam a extensão da função. O termo int
define a função "main" como sendo uma função que retorna um número inteiro. O termo void
indica que a função não aceita parâmetros.
A linha seguinte "chama", ou executa uma função chamada printf
; o ficheiro incluido, stdio.h
, contém a informação que descreve a forma como a função printf
poderá ser chamada. Nesta chamada, é passado à função printf
um único argumento, a linha de texto constante "Olá, Mundo!\n"; O \n é traduzido num caracter de "nova linha", que quando se envia para a saída-padrão faz com que o texto seguinte seja escrito na linha imediatamente abaixo. A função printf
retorna um valor, um int
, mas como não é usado ela é descartada pelo compilador. O depoimento return
ordena ao programa a saída da função que se encontra correntemente (neste caso a função main
), devolvendo o valor zero à função que a invocou. Como a função actual é a função main
, a função que a invocou é seja o que for que iniciou o programa. Por fim, o caracter }
indica o fim da função main
.
Note-se que texto rodeado por /*
e */
(comentários de texto) é ignorado pelo compilador. Os compiladores que obedecem à norma C99 também aceitam como comentários as linhas de texto que são precedidos por //
.
Ferramentas de programação
Ver também
Ligações externas
- Introdução à Programação C
- C: "A" Linguagem de Programação
- Precedência entre operadores em C
- (em inglês) Standard C
- (em inglês) C Programming
- (em inglês) C Programming Reference
- (em inglês) The Unofficial C for Dummies FAQ Page
- (em inglês) C optimisation tutorial
af:C (programmeertaal) als:C (Programmiersprache) am:ሲ (የኮምፒዩተር ፍርገማ ቋንቋ) an:Lenguache de programazión C ar:سي ast:Llinguaxe de programación C az:C (proqramlaşdırma dili) bat-smg:C be:Мова праграмавання C be-x-old:C (мова праграмавання) bg:C (език за програмиране) bn:সি (প্রোগ্রামিং ভাষা) br:Areg C bs:C programski jezik bug:C (basa maprogram) ca:Llenguatge C cdo:C ngṳ̄-ngiòng co:C (linguagiu) cs:C (programovací jazyk) cy:C (cyfrifiadureg) da:C (programmeringssprog) de:C (Programmiersprache) el:C (γλώσσα προγραμματισμού) en:C (programming language) eo:C (programlingvo) es:Lenguaje de programación C et:C (programmeerimiskeel) eu:C (programazio lengoaia) fi:C (ohjelmointikieli) fr:C (langage) ga:C (Teanga ríomhchlárúcháin) gl:Linguaxe de programación C he:C (שפת תכנות) hr:C (programski jezik) hu:C programozási nyelv ia:C (linguage de programmation) id:C (bahasa pemrograman) is:C (forritunarmál) it:C (linguaggio) ja:C言語 kab:C (tameslayt) ko:C (프로그래밍 언어) ku:C (zimanê bernamekirinê) la:C (lingua programmationis) lt:C (kalba) lv:C (programmēšanas valoda) mk:C (програмски јазик) ml:സി mn:Программчлалын Си хэл ms:C (bahasa pengaturcaraan) nl:C (programmeertaal) nn:Programmeringsspråket C no:C (programmeringsspråk) pl:C (język programowania) ro:C (limbaj de programare) ru:Си (язык программирования) sh:C (jezik) simple:C (programming language) sk:C (programovací jazyk) sl:Programski jezik C sq:Gjuha programuese C sr:Програмски језик C sv:C (programspråk) ta:சி நிரலாக்கல் மொழி te:సీ th:ภาษาซี tr:C programlama dili uk:Сі (мова програмування) vi:C (ngôn ngữ lập trình) yi:C (פראגראם שפראך) zh:C语言 zh-min-nan:C (thêng-sek gí-giân) zh-yue:C程式語言