C (linguagem de programação)

Da Wikipédia, a enciclopédia livre
Ir para navegação Pular para pesquisar

C
Texto em letras maiúsculas com serifa azul-claro em fundo branco e letra Sans-serif azul-claro muito grande.
The C Programming Language [1] (muitas vezes referida como K&R ), o livro seminal sobre C
ParadigmaMulti-paradigma : imperativo ( procedimental ), estruturado
Projetado porDennis Ritchie
DesenvolvedorDennis Ritchie & Bell Labs (criadores); ANSI X3J11 ( ANSI C ); ISO / IEC JTC1 / SC22 / WG14 (ISO C)
Apareceu pela primeira vez1972 ; 49 anos atrás [2] ( 1972 )
Versão estável
C17 / junho de 2018 ; 3 anos atrás ( 06 2018 )
Versão de visualização
C2x ( N2731 ) / 18 de outubro de 2021 ; 35 dias atrás [3] ( 2021-10-18 )
Disciplina de digitaçãoEstático , fraco , manifesto , nominal
SOPlataforma cruzada
Extensões de nome de arquivo.CH
Local na rede Internetwww .iso .org / standard / 74528 .html
www .open-std .org / jtc1 / sc22 / wg14 /
Implementações principais
K&R C , GCC , Clang , Intel C , C ++ Builder , Microsoft Visual C ++ , Watcom C
Dialetos
Cyclone , Unified Parallel C , Split-C , Cilk , C *
Influenciado por
B ( BCPL , CPL ), ALGOL 68 , [4] montagem , PL / I , FORTRAN
Influenciado
Numerosos : AMPL , AWK , csh , C ++ , C-- , C # , Objective-C , D , Go , Java , JavaScript , Julia , Limbo , LPC , Perl , PHP , Pike , Processing , Python , Rust , Seed7 , Vala , Verilog (HDL), [5] Nim , Zig

C ( / s i / , como na letra c ) é um de uso geral , processual computador linguagem de programação apoiando programação estruturada , âmbito variável lexical , e a recursividade , com um sistema do tipo estático . Por design, C fornece construções que mapeiam com eficiência para instruções de máquina típicas . Ele encontrou uso duradouro em aplicativos previamente codificados em linguagem assembly . Esses aplicativos incluem sistemas operacionais e vários softwares de aplicativospara arquiteturas de computador que variam de supercomputadores a PLCs e sistemas embarcados .

Um sucessor da linguagem de programação B , C foi originalmente desenvolvido no Bell Labs por Dennis Ritchie entre 1972 e 1973 para construir utilitários rodando em Unix . Foi aplicado para reimplementar o kernel do sistema operacional Unix. [6] Durante a década de 1980, C gradualmente ganhou popularidade. Tornou-se uma das linguagens de programação mais amplamente utilizadas , [7] [8] com compiladores C de vários fornecedores disponíveis para a maioria das arquiteturas de computador e sistemas operacionais existentes. C foi padronizado pela ANSI desde 1989 ( ANSI C ) e pelaOrganização Internacional de Normalização (ISO).

C é uma linguagem procedural imperativa . Ele foi projetado para ser compilado para fornecer acesso de baixo nível à memória e construções de linguagem que mapeiam de forma eficiente para instruções de máquina , tudo com suporte mínimo de tempo de execução . Apesar de seus recursos de baixo nível, a linguagem foi projetada para encorajar a programação de plataforma cruzada. Um programa C compatível com os padrões escrito tendo em mente a portabilidade pode ser compilado para uma ampla variedade de plataformas de computador e sistemas operacionais com poucas alterações em seu código-fonte. [9]

Desde 2000, C tem consistentemente classificado entre as duas principais linguagens no índice TIOBE , uma medida da popularidade das linguagens de programação. [10]

Visão geral

Dennis Ritchie (à direita), o inventor da linguagem de programação C, com Ken Thompson

Como a maioria das linguagens procedurais na tradição ALGOL , C tem recursos para programação estruturada e permite escopo e recursão de variáveis ​​lexicais . Seu sistema de tipo estático evita operações indesejadas. Em C, todo código executável está contido em sub-rotinas (também chamadas de "funções", embora não estritamente no sentido de programação funcional ). Os parâmetros da função são sempre passados ​​por valor (exceto matrizes ). A passagem por referência é simulada em C, passando explicitamente os valores do ponteiro . O texto-fonte do programa C tem formato livre , usando ponto - e - vírgulacomo um terminador de instrução e chaves para agrupar blocos de instruções .

A linguagem C também exibe as seguintes características:

  • A linguagem tem um número pequeno, fixo de palavras-chave, incluindo um conjunto completo de fluxo de controle primitivos: if/else, for, do/while, while, e switch. Os nomes definidos pelo usuário não são distinguidos das palavras-chave por nenhum tipo de sigilo .
  • Ele tem um grande número de aritmética, bit a bit, e operadores lógicos: +, +=, ++, &, ||, etc.
  • Mais de uma atribuição pode ser realizada em uma única instrução.
  • Funções:
    • Os valores de retorno da função podem ser ignorados, quando não são necessários.
    • Ponteiros de função e dados permitem polimorfismo de tempo de execução ad hoc .
    • As funções não podem ser definidas dentro do escopo léxico de outras funções.
  • A tipagem de dados é estática , mas fracamente aplicada ; todos os dados têm um tipo, mas as conversões implícitas são possíveis.
  • A sintaxe da declaração imita o contexto de uso. C não tem palavra-chave "definir"; em vez disso, uma instrução começando com o nome de um tipo é considerada uma declaração. Não há palavra-chave "função"; em vez disso, uma função é indicada pela presença de uma lista de argumentos entre parênteses.
  • Os tipos definidos pelo usuário ( typedef ) e compostos são possíveis.
    • Os tipos de dados agregados heterogêneos ( struct) permitem que os elementos de dados relacionados sejam acessados ​​e atribuídos como uma unidade.
    • União é uma estrutura com membros sobrepostos; apenas o último membro armazenado é válido.
    • A indexação de matriz é uma notação secundária, definida em termos de aritmética de ponteiro. Ao contrário dos structs, os arrays não são objetos de primeira classe: eles não podem ser atribuídos ou comparados usando operadores internos únicos. Não há palavra-chave "array" em uso ou definição; em vez disso, os colchetes indicam matrizes sintaticamente, por exemplo month[11].
    • Tipos enumerados são possíveis com a enumpalavra - chave. Eles são livremente conversíveis com inteiros.
    • Strings não são um tipo de dados distinto, mas são convencionalmente implementados como matrizes de caracteres terminados em nulo .
  • O acesso de baixo nível à memória do computador é possível convertendo endereços de máquina em ponteiros digitados .
  • Procedimentos (sub-rotinas que não retornam valores) são um caso especial de função, com um tipo de retorno não tipado void.
  • Um pré-processador executa a definição de macro , inclusão de arquivo de código-fonte e compilação condicional .
  • Existe uma forma básica de modularidade : os arquivos podem ser compilados separadamente e vinculados , com controle sobre quais funções e objetos de dados são visíveis para outros arquivos por meio de statice externatributos.
  • Funcionalidades complexas, como E / S , manipulação de strings e funções matemáticas, são delegadas de forma consistente às rotinas da biblioteca .

Embora C não inclua certos recursos encontrados em outras linguagens (como orientação a objetos e coleta de lixo ), eles podem ser implementados ou emulados, geralmente por meio do uso de bibliotecas externas (por exemplo, o GLib Object System ou o coletor de lixo Boehm ).

Relações com outros idiomas

Muitas linguagens posteriores emprestaram direta ou indiretamente de C, incluindo C ++ , C # , shell C do Unix , D , Go , Java , JavaScript (incluindo transpiladores ), Julia , Limbo , LPC , Objective-C , Perl , PHP , Python , Ruby , Rust , Swift , Verilog e SystemVerilog (linguagens de descrição de hardware). [5] Essas linguagens extraíram muitas de suas estruturas de controle e outros recursos básicos de C. A maioria delas (Python sendo uma exceção dramática) também expressa uma sintaxe altamente semelhante a C e tendem a combinar a expressão reconhecível e a sintaxe de instrução de C com o tipo subjacente sistemas, modelos de dados e semântica que podem ser radicalmente diferentes.

História

Desenvolvimentos início

Linha do tempo de desenvolvimento da linguagem
Ano Padrão C [9]
1972 Nascimento
1978 K&R C
1989/1990 ANSI C e ISO C
1999 C99
2011 C11
2017 C17
TBD C2x

A origem do C está intimamente ligada ao desenvolvimento do sistema operacional Unix , originalmente implementado em linguagem assembly em um PDP-7 por Dennis Ritchie e Ken Thompson, incorporando várias ideias de colegas. Eventualmente, eles decidiram portar o sistema operacional para um PDP-11 . A versão PDP-11 original do Unix também foi desenvolvida em linguagem assembly. [6]

Thompson desejava uma linguagem de programação para fazer utilitários para a nova plataforma. No início, ele tentou fazer um compilador Fortran , mas logo desistiu da ideia. Em vez disso, ele criou uma versão reduzida da linguagem de programação de sistemas BCPL desenvolvida recentemente . A descrição oficial do BCPL não estava disponível na época, [11] e Thompson modificou a sintaxe para ser menos prolixo, produzindo o B semelhante, mas um tanto mais simples . [6] No entanto, poucos utilitários foram escritos em B porque era muito lento, e B não podia tirar proveito dos recursos do PDP-11, como endereçamento de byte .

Em 1972, Ritchie começou a melhorar B, mais notavelmente adicionando tipagem de dados para variáveis, o que resultou na criação de uma nova linguagem C. [12] O compilador C e alguns utilitários feitos com ele foram incluídos na Versão 2 do Unix . [13]

Na versão 4 do Unix , lançada em novembro de 1973, o kernel do Unix foi amplamente reimplementado em C. [6] Nessa época, a linguagem C havia adquirido alguns recursos poderosos, como os tipos. struct

O pré-processador foi introduzido por volta de 1973 por solicitação de Alan Snyder e também em reconhecimento à utilidade dos mecanismos de inclusão de arquivo disponíveis em BCPL e PL / I. Sua versão original fornecia apenas arquivos e substituições simples de strings: #includee #definede macros sem parâmetros. Logo depois disso, foi estendido, principalmente por Mike Lesk e depois por John Reiser, para incorporar macros com argumentos e compilação condicional. [6]

O Unix foi um dos primeiros kernels de sistema operacional implementado em uma linguagem diferente do assembly . Instâncias anteriores incluem o sistema Multics (que foi escrito em PL / I ) e o Master Control Program (MCP) para o Burroughs B5000 (que foi escrito em ALGOL ) em 1961. Por volta de 1977, Ritchie e Stephen C. Johnson fizeram novas alterações em o idioma para facilitar a portabilidade do sistema operacional Unix. O compilador portátil C de Johnson serviu de base para várias implementações de C em novas plataformas. [12]

K&R C

A capa do livro The C Programming Language , primeira edição, de Brian Kernighan e Dennis Ritchie

Em 1978, Brian Kernighan e Dennis Ritchie publicaram a primeira edição de The C Programming Language . [1] Este livro, conhecido pelos programadores C como K&R , serviu por muitos anos como uma especificação informal da linguagem. A versão de C que descreve é ​​comumente referida como " K&R C ". Como foi lançado em 1978, também é conhecido como C78 . [14] A segunda edição do livro [15] cobre o padrão ANSI C posterior , descrito abaixo.

K&R introduziu vários recursos de linguagem:

  • Biblioteca I / O padrão
  • long int tipo de dados
  • unsigned int tipo de dados
  • Operadores de atribuição compostos da forma (como ) foram alterados para a forma (isto é, ) para remover a ambigüidade semântica criada por construções como , que tinha sido interpretado como (decremento em 10) em vez do possivelmente pretendido (deixe ser - 10).=op=-op=-=i=-10i =- 10ii = -10i

Mesmo após a publicação do padrão ANSI de 1989, por muitos anos K&R C ainda era considerado o " menor denominador comum " ao qual os programadores C se restringiam quando a portabilidade máxima era desejada, uma vez que muitos compiladores mais antigos ainda estavam em uso, e porque K&R cuidadosamente escrito O código C também pode ser o padrão C legal.

Nas primeiras versões do C, apenas as funções que retornam tipos diferentes de intdevem ser declaradas se usadas antes da definição da função; funções usadas sem declaração prévia foram presumidas para retornar tipo int.

Por exemplo:

long some_function (); 
/ * int * / other_function (); 

/ * int * / calling_function () 
{
    long test1 ; 
    registrar / * int * / test2 ;  

    teste1 = alguma_função ();  
    if ( test1 > 1 )   
          test2 = 0 ;  
    outro
          test2 = outra_função ();  
    return test2 ; 
}

Os intespecificadores de tipo comentados podem ser omitidos em K&R C, mas são exigidos em padrões posteriores.

Como as declarações de função K&R não incluíam nenhuma informação sobre os argumentos da função, as verificações do tipo de parâmetro da função não foram realizadas, embora alguns compiladores emitissem uma mensagem de aviso se uma função local fosse chamada com o número errado de argumentos ou se várias chamadas para uma função externa usou diferentes números ou tipos de argumentos. Ferramentas separadas, como o utilitário lint do Unix, foram desenvolvidas que (entre outras coisas) podem verificar a consistência do uso da função em vários arquivos de origem.

Nos anos seguintes à publicação de K&R C, vários recursos foram adicionados à linguagem, suportados por compiladores da AT&T (em particular PCC [16] ) e alguns outros fornecedores. Estes incluíam:

O grande número de extensões e a falta de acordo sobre uma biblioteca padrão , juntamente com a popularidade da linguagem e o fato de nem mesmo os compiladores Unix implementarem com precisão a especificação K&R, levaram à necessidade de padronização.

ANSI C e ISO C

Durante o final dos anos 1970 e 1980, as versões do C foram implementadas para uma ampla variedade de computadores mainframe , minicomputadores e microcomputadores , incluindo o IBM PC , conforme sua popularidade começou a aumentar significativamente.

Em 1983, o American National Standards Institute (ANSI) formou um comitê, X3J11, para estabelecer uma especificação padrão de C. X3J11 com base no padrão C na implementação do Unix; entretanto, a parte não portátil da biblioteca Unix C foi entregue ao grupo de trabalho 1003 do IEEE para se tornar a base para o padrão POSIX de 1988 . Em 1989, o padrão C foi ratificado como ANSI X3.159-1989 "Linguagem de Programação C". Esta versão da linguagem é freqüentemente referida como ANSI C , Padrão C ou, às vezes, C89.

Em 1990, o padrão ANSI C (com alterações de formatação) foi adotado pela Organização Internacional de Padronização (ISO) como ISO / IEC 9899: 1990, às vezes chamado de C90. Portanto, os termos "C89" e "C90" referem-se à mesma linguagem de programação.

O ANSI, como outros organismos de normalização nacionais, não desenvolve mais o padrão C de forma independente, mas segue o padrão C internacional, mantido pelo grupo de trabalho ISO / IEC JTC1 / SC22 / WG14. A adoção nacional de uma atualização do padrão internacional normalmente ocorre dentro de um ano da publicação da ISO.

Um dos objetivos do processo de padronização C era produzir um superconjunto de K&R C, incorporando muitos dos recursos não oficiais introduzidos posteriormente. O comitê de padrões também incluiu vários recursos adicionais, como protótipos de função (emprestados do C ++), voidponteiros, suporte para conjuntos de caracteres e localidades internacionais e aprimoramentos de pré-processador. Embora a sintaxe para declarações de parâmetro tenha sido aumentada para incluir o estilo usado em C ++, a interface K&R continuou a ser permitida, para compatibilidade com o código-fonte existente.

O C89 é compatível com os compiladores C atuais e a maioria dos códigos C modernos é baseado nele. Qualquer programa escrito apenas em C padrão e sem quaisquer suposições dependentes de hardware será executado corretamente em qualquer plataforma com uma implementação C em conformidade, dentro de seus limites de recursos. Sem tais precauções, os programas podem compilar apenas em uma determinada plataforma ou com um compilador específico, devido, por exemplo, ao uso de bibliotecas não padrão, como bibliotecas GUI , ou a uma dependência de atributos específicos do compilador ou da plataforma, como como o tamanho exato dos tipos de dados e endianness de bytes .

Nos casos em que o código deve ser compilado por compiladores em conformidade com o padrão ou com base em K&R C, a __STDC__macro pode ser usada para dividir o código em seções Standard e K&R para evitar o uso em um compilador baseado em K&R C de recursos disponíveis apenas em Standard C.

Após o processo de padronização ANSI / ISO, a especificação da linguagem C permaneceu relativamente estática por vários anos. Em 1995, a Emenda Normativa 1 ao padrão C de 1990 (ISO / IEC 9899 / AMD1: 1995, conhecido informalmente como C95) foi publicada, para corrigir alguns detalhes e adicionar suporte mais amplo para conjuntos de caracteres internacionais. [17]

C99

1999 ISO C.pdf

O padrão C foi revisado posteriormente no final da década de 1990, levando à publicação da ISO / IEC 9899: 1999 em 1999, que é comumente referida como " C99 ". Desde então, foi alterado três vezes pela Technical Corrigenda. [18]

C99 introduziu vários novos recursos, incluindo funções inline , vários novos tipos de dados (incluindo long long inte um complextipo para representar números complexos ), matrizes de comprimento variável e membros de matriz flexível , suporte aprimorado para ponto flutuante IEEE 754 , suporte para macros variadic (macros de variável aridade ) e suporte para comentários de uma linha começando com //, como em BCPL ou C ++. Muitos deles já foram implementados como extensões em vários compiladores C.

O C99 é em sua maior parte compatível com versões anteriores do C90, mas é mais rígido em alguns aspectos; em particular, uma declaração que carece de um especificador de tipo não é mais intassumida implicitamente. Uma macro padrão __STDC_VERSION__é definida com valor 199901Lpara indicar que o suporte C99 está disponível. GCC , Solaris Studio e outros compiladores C agora oferecem suporte a muitos ou todos os novos recursos do C99. O compilador C no Microsoft Visual C ++ , entretanto, implementa o padrão C89 e as partes do C99 que são necessárias para compatibilidade com o C ++ 11 . [19] [ precisa de atualização ]

Além disso, o suporte para identificadores Unicode (nomes de variáveis ​​/ funções) na forma de caracteres de escape (por exemplo \U0001f431) agora é necessário. O suporte para nomes Unicode brutos é opcional.

C11

Em 2007, o trabalho começou em outra revisão do padrão C, informalmente chamada de "C1X" até sua publicação oficial em 08/12/2011. O comitê de padrões C adotou diretrizes para limitar a adoção de novos recursos que não foram testados pelas implementações existentes.

O padrão C11 adiciona vários novos recursos ao C e à biblioteca, incluindo macros genéricas de tipo, estruturas anônimas, suporte Unicode aprimorado, operações atômicas, multithreading e funções com verificação de limites. Também torna opcionais algumas partes da biblioteca C99 existente e melhora a compatibilidade com C ++. A macro padrão __STDC_VERSION__é definida 201112Lpara indicar que o suporte C11 está disponível.

C17

Publicado em junho de 2018, C17 é o padrão atual para a linguagem de programação C. Ele não apresenta novos recursos de linguagem, apenas correções técnicas e esclarecimentos para defeitos no C11. A macro padrão __STDC_VERSION__é definida como 201710L.

C2x

C2x é um nome informal para a próxima revisão principal da linguagem C (após C17). Prevê-se que seja votado em 2023 e, portanto, seria denominado C23. [20] [ melhor fonte necessária ]

Embutido C

Historicamente, a programação C incorporada requer extensões não padronizadas para a linguagem C a fim de oferecer suporte a recursos exóticos, como aritmética de ponto fixo , vários bancos de memória distintos e operações básicas de E / S.

Em 2008, o Comitê de Padrões C publicou um relatório técnico estendendo a linguagem C [21] para abordar esses problemas, fornecendo um padrão comum para todas as implementações aderirem. Inclui vários recursos não disponíveis em C normal, como aritmética de ponto fixo , espaços de endereço nomeados e endereçamento de hardware de E / S básico.

Sintaxe

C tem uma gramática formal especificada pelo padrão C. [22] As terminações de linha geralmente não são significativas em C; no entanto, os limites da linha têm significância durante a fase de pré-processamento. Os comentários podem aparecer entre os delimitadores /*e */, ou (desde C99) seguindo //até o final da linha. Comentários delimitados por /*e */não aninhados e essas sequências de caracteres não são interpretadas como delimitadores de comentários se aparecerem dentro de strings ou literais de caracteres. [23]

Os arquivos de origem C contêm declarações e definições de funções. As definições de função, por sua vez, contêm declarações e instruções . As declarações definem novos tipos usando palavras-chave como struct, unione enum, ou atribuem tipos e talvez reservem armazenamento para novas variáveis, geralmente escrevendo o tipo seguido pelo nome da variável. Palavras-chave como chare intespecificar tipos integrados. As seções do código são colocadas entre colchetes ( {e }, às vezes chamadas de "chaves") para limitar o escopo das declarações e atuar como uma única instrução para estruturas de controle.

Como uma linguagem imperativa, C usa instruções para especificar ações. A declaração mais comum é uma declaração de expressão , consistindo em uma expressão a ser avaliada, seguida por um ponto e vírgula; como um efeito colateral da avaliação, as funções podem ser chamados e variáveis podem ser atribuídos novos valores. Para modificar a execução sequencial normal de instruções, C fornece várias instruções de fluxo de controle identificadas por palavras-chave reservadas. Programação estruturada é apoiado por if... [ else] execução condicional e por do... while, whilee forexecução iterativo (loop). oforinstrução tem expressões separadas de inicialização, teste e reinicialização, qualquer uma ou todas podem ser omitidas. breake continuepode ser usado para deixar a instrução de loop envolvente mais interna ou pular para sua reinicialização. Também existe uma gotoinstrução não estruturada que se ramifica diretamente para o rótulo designado dentro da função. switchseleciona um casea ser executado com base no valor de uma expressão inteira.

As expressões podem usar uma variedade de operadores integrados e podem conter chamadas de função. A ordem na qual os argumentos para funções e operandos para a maioria dos operadores são avaliados não é especificada. As avaliações podem até ser intercaladas. No entanto, todos os efeitos colaterais (incluindo armazenamento de variáveis) ocorrerão antes do próximo " ponto de sequência "; os pontos de sequência incluem o final de cada instrução de expressão e a entrada e o retorno de cada chamada de função. Os pontos de sequência também ocorrer durante a avaliação de certas expressões contendo operadores ( &&, ||, ?:e o operador de vírgula) Isso permite um alto grau de otimização do código do objeto pelo compilador, mas requer que os programadores C tomem mais cuidado para obter resultados confiáveis ​​do que o necessário para outras linguagens de programação.

Kernighan e Ritchie dizem na introdução da linguagem de programação C : "C, como qualquer outra linguagem, tem suas manchas. Alguns dos operadores têm precedência errada; algumas partes da sintaxe poderiam ser melhores." [24] O padrão C não tentou corrigir muitas dessas manchas, por causa do impacto de tais mudanças no software já existente.

Conjunto de caracteres

O conjunto básico de caracteres de origem C inclui os seguintes caracteres:

Nova linha indica o fim de uma linha de texto; não precisa corresponder a um único caractere real, embora, por conveniência, C o trate como um.

Caracteres codificados multibyte adicionais podem ser usados ​​em literais de string, mas não são totalmente portáteis . O padrão C mais recente ( C11 ) permite que caracteres Unicode multinacionais sejam incorporados portavelmente no texto de origem C usando \uXXXXou \UXXXXXXXXcodificação (onde Xdenota um caractere hexadecimal), embora esse recurso ainda não seja amplamente implementado.

O conjunto básico de caracteres de execução C contém os mesmos caracteres, junto com representações para alerta , retrocesso e retorno de carro . O suporte em tempo de execução para conjuntos de caracteres estendidos aumentou com cada revisão do padrão C.

Palavras reservadas

C89 tem 32 palavras reservadas, também conhecidas como palavras-chave, que são palavras que não podem ser usadas para outros fins que não aqueles para os quais foram predefinidas:

C99 reservou mais cinco palavras:

C11 reservou mais sete palavras: [25]

  • _Alignas
  • _Alignof
  • _Atomic
  • _Generic
  • _Noreturn
  • _Static_assert
  • _Thread_local

A maioria das palavras reservadas recentemente começa com um sublinhado seguido por uma letra maiúscula, porque os identificadores dessa forma eram anteriormente reservados pelo padrão C para uso apenas por implementações. Visto que o código-fonte do programa existente não deveria estar usando esses identificadores, ele não seria afetado quando as implementações C começassem a oferecer suporte a essas extensões para a linguagem de programação. Alguns cabeçalhos padrão definem sinônimos mais convenientes para identificadores sublinhados. A linguagem anteriormente incluía uma palavra reservada chamada entry, mas isso raramente era implementado e agora foi removido como uma palavra reservada. [26]

Operadores

C oferece suporte a um rico conjunto de operadores , que são símbolos usados ​​em uma expressão para especificar as manipulações a serem realizadas durante a avaliação dessa expressão. C tem operadores para:

C usa o operador =(usado em matemática para expressar igualdade) para indicar atribuição, seguindo o precedente de Fortran e PL / I , mas ao contrário de ALGOL e suas derivadas. C usa o operador ==para testar a igualdade. A semelhança entre esses dois operadores (atribuição e igualdade) pode resultar no uso acidental de um no lugar do outro e, em muitos casos, o erro não produz uma mensagem de erro (embora alguns compiladores produzam avisos). Por exemplo, a expressão condicional if (a == b + 1)pode ser escrita por engano como if (a = b + 1), que será avaliada como verdadeira se anão for zero após a atribuição. [27]

A precedência do operador C nem sempre é intuitiva. Por exemplo, o operador ==vincula-se mais fortemente do que (é executado antes de) os operadores &(bit a bit AND) e |(bit a bit OR) em expressões como x & 1 == 0, que deve ser escrita como (x & 1) == 0se essa fosse a intenção do codificador. [28]

"Olá, mundo" exemplo

"Olá Mundo!" programa de Brian Kernighan (1978)

O exemplo " olá, mundo ", que apareceu na primeira edição do K&R , tornou-se o modelo para um programa introdutório na maioria dos livros de programação. O programa imprime "hello, world" na saída padrão , que geralmente é um terminal ou exibição na tela.

A versão original era: [29]

principal ()
{
    printf ( "olá, mundo \ n " );
}

Um programa "hello, world" em conformidade com o padrão é: [a]

#include <stdio.h> 

int main ( vazio ) 
{
    printf ( "olá, mundo \ n " );
}

A primeira linha do programa contém uma diretiva de pré - processamento , indicada por #include. Isso faz com que o compilador substitua essa linha por todo o texto do stdio.hcabeçalho padrão, que contém declarações para funções de entrada e saída padrão, como printfe scanf. Os colchetes angulares stdio.hindicam que stdio.hestá localizado usando uma estratégia de pesquisa que prefere cabeçalhos fornecidos com o compilador a outros cabeçalhos com o mesmo nome, em oposição a aspas duplas que normalmente incluem arquivos de cabeçalho locais ou específicos do projeto.

A próxima linha indica que uma função chamada mainestá sendo definida. A mainfunção tem um propósito especial em programas C; o ambiente de tempo de execução chama a mainfunção para iniciar a execução do programa. O especificador de tipo intindica que o valor que é retornado ao invocador (neste caso, o ambiente de tempo de execução) como resultado da avaliação da mainfunção, é um número inteiro. A palavra-chave voidcomo uma lista de parâmetros indica que esta função não aceita argumentos. [b]

A chave de abertura indica o início da definição da mainfunção.

A próxima linha chama (desvia a execução para) uma função chamada printf, que neste caso é fornecida a partir de uma biblioteca do sistema . Nesta chamada, a printffunção é passada (fornecida com) um único argumento, o endereço do primeiro caractere no literal da string"hello, world\n" . O literal de string é um array sem nome com elementos do tipo char, configurado automaticamente pelo compilador com um caractere final com valor 0 para marcar o fim do array ( printfprecisa saber isso). O \né uma seqüência de escape que C traduz em um caractere de nova linha , que na saída significa o fim da linha atual. O valor de retorno doprintffunção é do tipo int, mas é descartada silenciosamente, uma vez que não é usada. (Um programa mais cuidadoso pode testar o valor de retorno para determinar se a printffunção foi bem-sucedida ou não .) O ponto-e-vírgula ;termina a instrução.

A chave de fechamento indica o fim do código para a mainfunção. De acordo com a especificação C99 e mais recentes, a mainfunção, ao contrário de qualquer outra função, retornará implicitamente um valor de 0ao atingir o }que termina a função. (Anteriormente, uma return 0;instrução explícita era necessária.) Isso é interpretado pelo sistema de tempo de execução como um código de saída indicando uma execução bem-sucedida. [30]

Tipos de dados

O sistema de tipos em C é estático e fracamente tipado , o que o torna semelhante ao sistema de tipos dos descendentes do ALGOL , como Pascal . [31] Existem tipos embutidos para inteiros de vários tamanhos, tanto com sinal quanto sem sinal, números de ponto flutuante e tipos enumerados ( enum). O tipo inteiro charé freqüentemente usado para caracteres de byte único. C99 adicionou um tipo de dados booleano . Também existem tipos derivados, incluindo matrizes , ponteiros , registros ( struct) e uniões ( union).

C é freqüentemente usado na programação de sistemas de baixo nível, onde fugas do sistema de tipo podem ser necessárias. O compilador tenta garantir a exatidão do tipo da maioria das expressões, mas o programador pode substituir as verificações de várias maneiras, usando uma conversão de tipo para converter explicitamente um valor de um tipo para outro ou usando ponteiros ou uniões para reinterpretar os bits subjacentes de um objeto de dados de alguma outra maneira.

Alguns acham a sintaxe de declaração do C não intuitiva, particularmente para ponteiros de função . (A ideia de Ritchie era declarar identificadores em contextos semelhantes ao seu uso: "a declaração reflete o uso ".) [32]

As conversões aritméticas usuais de C permitem a geração de código eficiente, mas às vezes podem produzir resultados inesperados. Por exemplo, uma comparação de inteiros assinados e não assinados de largura igual requer uma conversão do valor assinado em não assinado. Isso pode gerar resultados inesperados se o valor com sinal for negativo.

Ponteiros

C suporta o uso de ponteiros , um tipo de referência que registra o endereço ou localização de um objeto ou função na memória. Os ponteiros podem ser referenciados para acessar dados armazenados no endereço apontado ou para invocar uma função apontada. Os ponteiros podem ser manipulados por meio de atribuição ou aritmética de ponteiros . A representação em tempo de execução de um valor de ponteiro é normalmente um endereço de memória bruto (talvez aumentado por um campo de deslocamento dentro da palavra), mas uma vez que o tipo de um ponteiro inclui o tipo da coisa apontada, expressões incluindo ponteiros podem ser verificados por tipo em tempo de compilação. A aritmética do ponteiro é dimensionada automaticamente pelo tamanho do tipo de dados apontado. Os ponteiros são usados ​​para muitos propósitos em C. Strings de textosão comumente manipulados usando ponteiros em matrizes de caracteres. A alocação de memória dinâmica é realizada por meio de ponteiros. Muitos tipos de dados, como árvores , são comumente implementados como structobjetos alocados dinamicamente e vinculados por meio de ponteiros. Ponteiros para funções são úteis para passar funções como argumentos para funções de ordem superior (como qsort ou bsearch ) ou como retornos de chamada a serem invocados por manipuladores de eventos. [30]

Um valor de ponteiro nulo aponta explicitamente para nenhum local válido. O cancelamento da referência de um valor de ponteiro nulo é indefinido, geralmente resultando em uma falha de segmentação . Os valores de ponteiro nulos são úteis para indicar casos especiais, como nenhum ponteiro "próximo" no nó final de uma lista vinculada , ou como uma indicação de erro de funções que retornam ponteiros. Em contextos apropriados no código-fonte, como para atribuir a uma variável de ponteiro, uma constante de ponteiro nula pode ser escrita como 0, com ou sem conversão explícita para um tipo de ponteiro, ou como a NULLmacro definida por vários cabeçalhos padrão. Em contextos condicionais, os valores de ponteiro nulos são avaliados como falsos, enquanto todos os outros valores de ponteiros são avaliados como verdadeiros.

Os ponteiros void ( void *) apontam para objetos de tipo não especificado e, portanto, podem ser usados ​​como ponteiros de dados "genéricos". Como o tamanho e o tipo do objeto apontado não são conhecidos, os ponteiros vazios não podem ser desreferenciados, nem a aritmética de ponteiros neles é permitida, embora possam ser facilmente (e em muitos contextos implicitamente são) convertidos de e para qualquer outro ponteiro de objeto modelo. [30]

O uso descuidado de ponteiros é potencialmente perigoso. Como normalmente não são verificados, uma variável de ponteiro pode ser feita para apontar para qualquer local arbitrário, o que pode causar efeitos indesejáveis. Embora ponteiros usados ​​corretamente apontem para locais seguros, eles podem ser feitos para apontar para locais inseguros usando aritmética de ponteiro inválida ; os objetos para os quais eles apontam podem continuar a ser usados ​​após a desalocação ( ponteiros pendentes ); podem ser usados ​​sem terem sido inicializados ( wild pointers); ou podem ser atribuídos diretamente a um valor inseguro usando um elenco, união ou por meio de outro ponteiro corrompido. Em geral, C é permissivo ao permitir a manipulação e a conversão entre os tipos de ponteiro, embora os compiladores normalmente forneçam opções para vários níveis de verificação. Algumas outras linguagens de programação tratam desses problemas usando tipos de referência mais restritivos .

Matrizes

Os tipos de array em C são tradicionalmente de um tamanho fixo e estático especificado em tempo de compilação. O padrão C99 mais recente também permite uma forma de matrizes de comprimento variável. No entanto, também é possível alocar um bloco de memória (de tamanho arbitrário) em tempo de execução, usando a mallocfunção da biblioteca padrão , e tratá-lo como um array.

Como as matrizes são sempre acessadas (na verdade) por meio de ponteiros, os acessos à matriz normalmente não são verificados em relação ao tamanho da matriz subjacente, embora alguns compiladores possam fornecer a verificação de limites como uma opção. [33] [34] Violações de limites de matriz são, portanto, possíveis e podem levar a várias repercussões, incluindo acessos ilegais à memória, corrupção de dados, saturações de buffer e exceções de tempo de execução.

C não tem uma provisão especial para declarar arrays multidimensionais , mas depende da recursão dentro do sistema de tipos para declarar arrays de arrays, o que efetivamente realiza a mesma coisa. Os valores de índice da "matriz multidimensional" resultante podem ser considerados como crescentes na ordem da linha principal . Matrizes multidimensionais são comumente usadas em algoritmos numéricos (principalmente de álgebra linear aplicada) para armazenar matrizes. A estrutura do array C é adequada para essa tarefa específica. No entanto, nas primeiras versões de C, os limites do array devem ser valores fixos conhecidos ou então explicitamente passados ​​para qualquer sub-rotina que os requeira, e arrays de arrays dimensionados dinamicamente não podem ser acessados ​​usando indexação dupla. (Uma solução alternativa para isso era alocar a matriz com um "vetor de linha" adicional de ponteiros para as colunas.) C99 introduziu "matrizes de comprimento variável" que tratam desse problema.

O exemplo a seguir usando C moderno (C99 ou posterior) mostra a alocação de uma matriz bidimensional no heap e o uso de indexação de matriz multidimensional para acessos (que pode usar a verificação de limites em muitos compiladores C):

função int ( int N , int M )    
{
  float ( * p ) [ N ] [ M ] = malloc ( sizeof * p );    
  if ( ! p ) 
    return -1 ; 
  para ( int i = 0 ; i < N ; i ++ )        
    para ( int j = 0 ; j < M ; j ++ )        
      ( * p ) [ i ] [ j ] = i + j ;    
  print_array ( N , M , p );  
  livre ( p );
  return 1 ; 
}

Matriz ponteiro permutabilidade

A notação subscrita x[i](onde xdesigna um ponteiro) é um açúcar sintático para *(x+i). [35] Aproveitando o conhecimento do compilador do tipo de ponteiro, o endereço que x + iaponta não é o endereço base (apontado por x) incrementado por ibytes, mas sim definido como o endereço base incrementado por imultiplicado pelo tamanho de um elemento que xaponta para. Assim, x[i]designa o i+1ésimo elemento da matriz.

Além disso, na maioria dos contextos de expressão (uma exceção notável é como operando de sizeof), uma expressão do tipo array é automaticamente convertida em um ponteiro para o primeiro elemento do array. Isso implica que uma matriz nunca é copiada como um todo quando nomeada como um argumento para uma função, mas apenas o endereço de seu primeiro elemento é passado. Portanto, embora as chamadas de função em C usem semântica de passagem por valor , os arrays são, na verdade, passados ​​por referência .

O tamanho total de uma matriz xpode ser determinado aplicando-se sizeofa uma expressão do tipo matriz. O tamanho de um elemento pode ser determinado aplicando o operador sizeofa qualquer elemento não referenciado de uma matriz A, como em n = sizeof A[0]. Isso, o número de elementos em uma matriz declarada Apode ser determinado como sizeof A / sizeof A[0]. Observe que, se apenas um ponteiro para o primeiro elemento estiver disponível, como costuma ser o caso no código C, por causa da conversão automática descrita acima, as informações sobre o tipo completo da matriz e seu comprimento são perdidas.

Gerenciamento de memória

Uma das funções mais importantes de uma linguagem de programação é fornecer recursos para gerenciar a memória e os objetos que estão armazenados na memória. C fornece três maneiras distintas de alocar memória para objetos: [30]

  • Alocação de memória estática : o espaço para o objeto é fornecido no binário em tempo de compilação; esses objetos têm uma extensão (ou tempo de vida), desde que o binário que os contém seja carregado na memória.
  • Alocação automática de memória : os objetos temporários podem ser armazenados na pilha , e este espaço é automaticamente liberado e reutilizável após a saída do bloco em que foram declarados.
  • Alocação de memória dinâmica : blocos de memória de tamanho arbitrário podem ser solicitados em tempo de execução usando funções de biblioteca, como mallocde uma região da memória chamada heap ; esses blocos persistem até serem posteriormente liberados para reutilização, chamando a função de biblioteca reallocoufree

Essas três abordagens são apropriadas em diferentes situações e têm vários trade-offs. Por exemplo, a alocação de memória estática tem pouca sobrecarga de alocação, a alocação automática pode envolver um pouco mais de sobrecarga e a alocação de memória dinâmica pode potencialmente ter uma grande sobrecarga para alocação e desalocação. A natureza persistente de objetos estáticos é útil para manter informações de estado entre chamadas de função, a alocação automática é fácil de usar, mas o espaço de pilha é normalmente muito mais limitado e transiente do que a memória estática ou o espaço de heap, e a alocação de memória dinâmica permite a alocação conveniente de objetos cujo o tamanho é conhecido apenas em tempo de execução. A maioria dos programas C faz uso extensivo de todos os três.

Onde possível, a alocação automática ou estática é geralmente mais simples porque o armazenamento é gerenciado pelo compilador, liberando o programador da tarefa potencialmente sujeita a erros de alocar e liberar armazenamento manualmente. No entanto, muitas estruturas de dados podem mudar de tamanho em tempo de execução e, como as alocações estáticas (e alocações automáticas antes de C99) devem ter um tamanho fixo em tempo de compilação, há muitas situações em que a alocação dinâmica é necessária. [30] Antes do padrão C99, matrizes de tamanho variável eram um exemplo comum disso. (Veja o artigo sobremallocpara um exemplo de matrizes alocadas dinamicamente.) Ao contrário da alocação automática, que pode falhar em tempo de execução com consequências não controladas, as funções de alocação dinâmica retornam uma indicação (na forma de um valor de ponteiro nulo) quando o armazenamento necessário não pode ser alocado. (A alocação estática que é muito grande geralmente é detectada pelo vinculador ou carregador , antes mesmo que o programa possa começar a execução.)

A menos que especificado de outra forma, os objetos estáticos contêm valores de ponteiro nulos ou zero na inicialização do programa. Objetos alocados automática e dinamicamente são inicializados apenas se um valor inicial for especificado explicitamente; caso contrário, eles inicialmente têm valores indeterminados (normalmente, qualquer padrão de bits que esteja presente no armazenamento , o que pode nem mesmo representar um valor válido para aquele tipo). Se o programa tentar acessar um valor não inicializado, os resultados serão indefinidos. Muitos compiladores modernos tentam detectar e alertar sobre esse problema, mas tanto falsos positivos quanto falsos negativos podem ocorrer.

A alocação de memória heap deve ser sincronizada com seu uso real em qualquer programa para ser reutilizada tanto quanto possível. Por exemplo, se o único ponteiro para uma alocação de memória heap sai do escopo ou tem seu valor sobrescrito antes de ser desalocado explicitamente, essa memória não pode ser recuperada para reutilização posterior e é essencialmente perdida para o programa, um fenômeno conhecido como memória vazamento . Por outro lado, é possível que a memória seja liberada, mas é referenciada posteriormente, levando a resultados imprevisíveis. Normalmente, os sintomas de falha aparecem em uma parte do programa não relacionada ao código que causa o erro, dificultando o diagnóstico da falha. Esses problemas são amenizados em linguagens com coleta de lixo automática .

Bibliotecas

A linguagem de programação C usa bibliotecas como seu método principal de extensão. Em C, uma biblioteca é um conjunto de funções contidas em um único arquivo "archive". Cada biblioteca normalmente possui um arquivo de cabeçalho , que contém os protótipos das funções contidas na biblioteca que podem ser usadas por um programa e declarações de tipos de dados especiais e símbolos de macro usados ​​com essas funções. Para que um programa use uma biblioteca, ele deve incluir o arquivo de cabeçalho da biblioteca, e a biblioteca deve estar vinculada ao programa, o que em muitos casos requer sinalizadores de compilador (por exemplo -lm, abreviação para "vincular a biblioteca matemática"). [30]

A biblioteca C mais comum é a biblioteca padrão C , que é especificada pelos padrões ISO e ANSI C e vem com todas as implementações C (implementações que visam ambientes limitados, como sistemas embarcados, podem fornecer apenas um subconjunto da biblioteca padrão). Esta biblioteca suporta entrada e saída de fluxo, alocação de memória, matemática, cadeias de caracteres e valores de tempo. Vários cabeçalhos padrão separados (por exemplo, stdio.h) especificam as interfaces para esses e outros recursos de biblioteca padrão.

Outro conjunto comum de funções da biblioteca C são aquelas usadas por aplicativos direcionados especificamente para Unix e sistemas semelhantes ao Unix, especialmente funções que fornecem uma interface para o kernel . Essas funções são detalhadas em vários padrões, como POSIX e Single UNIX Specification .

Como muitos programas foram escritos em C, há uma grande variedade de outras bibliotecas disponíveis. As bibliotecas são frequentemente escritas em C porque os compiladores C geram código-objeto eficiente ; os programadores então criam interfaces para a biblioteca para que as rotinas possam ser usadas a partir de linguagens de nível superior como Java , Perl e Python . [30]

Manipulação de arquivos e fluxos

A entrada e saída de arquivos (E / S) não fazem parte da linguagem C em si, mas são gerenciadas por bibliotecas (como a biblioteca padrão C) e seus arquivos de cabeçalho associados (por exemplo stdio.h). O tratamento de arquivos geralmente é implementado por meio de E / S de alto nível, que funciona por meio de fluxos . Um fluxo é, dessa perspectiva, um fluxo de dados independente de dispositivos, enquanto um arquivo é um dispositivo concreto. A E / S de alto nível é feita por meio da associação de um fluxo a um arquivo. Na biblioteca padrão C, um buffer (uma área de memória ou fila) é usado temporariamente para armazenar dados antes de serem enviados ao destino final. Isso reduz o tempo gasto esperando por dispositivos mais lentos, por exemplo, um disco rígido ou unidade de estado sólido. As funções de E / S de baixo nível não fazem parte da biblioteca C padrão [ esclarecimento necessário ], mas geralmente fazem parte da programação "bare metal" (programação que é independente de qualquer sistema operacional , como a maioria da programação embarcada ). Com poucas exceções, as implementações incluem E / S de baixo nível.

Ferramentas de linguagem

Várias ferramentas foram desenvolvidas para ajudar os programadores C a encontrar e corrigir instruções com comportamento indefinido ou possivelmente expressões errôneas, com maior rigor do que o fornecido pelo compilador. A ferramenta lint foi a primeira, levando a muitas outras.

A verificação e auditoria automatizadas do código-fonte são benéficas em qualquer linguagem e, para C, existem muitas dessas ferramentas, como o Lint . Uma prática comum é usar o Lint para detectar código questionável quando um programa é escrito pela primeira vez. Depois que um programa é aprovado no Lint, ele é compilado usando o compilador C. Além disso, muitos compiladores podem opcionalmente alertar sobre construções sintaticamente válidas que provavelmente são erros. MISRA C é um conjunto proprietário de diretrizes para evitar esse tipo de código questionável, desenvolvido para sistemas embarcados. [36]

Existem também compiladores, bibliotecas e mecanismos de nível de sistema operacional para executar ações que não são uma parte padrão de C, como verificação de limites para matrizes, detecção de estouro de buffer , serialização , rastreamento de memória dinâmica e coleta de lixo automática .

Ferramentas como Purify ou Valgrind e vinculação com bibliotecas contendo versões especiais das funções de alocação de memória podem ajudar a descobrir erros de tempo de execução no uso de memória.

Usos

A linguagem de programação C

C é amplamente usado para programação de sistemas na implementação de sistemas operacionais e aplicativos de sistema embarcado , [37] porque o código C, quando escrito para portabilidade, pode ser usado para a maioria dos propósitos, mas quando necessário, o código específico do sistema pode ser usado para acessar hardware específico endereços e para realizar trocadilhos para atender aos requisitos de interface impostos externamente, com uma baixa demanda de tempo de execução nos recursos do sistema.

C pode ser usado para programação de site da Web usando a Common Gateway Interface (CGI) como um "gateway" para informações entre o aplicativo da Web, o servidor e o navegador. [38] C é frequentemente escolhido em vez de linguagens interpretadas por causa de sua velocidade, estabilidade e disponibilidade quase universal. [39]

Uma consequência da ampla disponibilidade e eficiência do C é que compiladores , bibliotecas e interpretadores de outras linguagens de programação são frequentemente implementados em C. Por exemplo, as implementações de referência de Python , Perl , Ruby e PHP são escritas em C.

C permite que os programadores criem implementações eficientes de algoritmos e estruturas de dados, porque a camada de abstração do hardware é fina e sua sobrecarga é baixa, um critério importante para programas computacionalmente intensivos. Por exemplo, a GNU Multiple Precision Arithmetic Library , a GNU Scientific Library , o Mathematica e o MATLAB são completa ou parcialmente escritos em C.

C às vezes é usado como uma linguagem intermediária por implementações de outras linguagens. Essa abordagem pode ser usada para portabilidade ou conveniência; usando C como uma linguagem intermediária, geradores de código específicos de máquina adicionais não são necessários. C tem alguns recursos, como diretivas de pré-processador de número de linha e vírgulas supérfluas opcionais no final das listas de inicializadores, que oferecem suporte à compilação do código gerado. No entanto, algumas das deficiências do C levaram ao desenvolvimento de outras linguagens baseadas em C projetadas especificamente para uso como linguagens intermediárias, como C-- .

C também tem sido amplamente usado para implementar aplicativos de usuário final . No entanto, esses aplicativos também podem ser escritos em linguagens mais recentes e de nível superior.

Línguas relacionadas

O gráfico de índice TIOBE , mostrando uma comparação da popularidade de várias linguagens de programação [40]

C influenciou direta e indiretamente muitas linguagens posteriores, como C # , D , Go , Java , JavaScript , Limbo , LPC , Perl , PHP , Python e o shell C do Unix . [41] A influência mais difundida foi sintática; todas as linguagens mencionadas combinam a sintaxe de instrução e (mais ou menos reconhecível) de expressão de C com sistemas de tipo, modelos de dados e / ou estruturas de programa em grande escala que diferem daqueles de C, às vezes radicalmente.

Existem vários intérpretes C ou near-C, incluindo Ch e CINT , que também podem ser usados ​​para scripts.

Quando as linguagens de programação orientadas a objetos se tornaram populares, C ++ e Objective-C eram duas extensões diferentes de C que forneciam recursos orientados a objetos. Ambas as linguagens foram implementadas originalmente como compiladores fonte-a-fonte ; o código-fonte foi traduzido para C e depois compilado com um compilador C. [42]

A linguagem de programação C ++ (originalmente chamada de "C com Classes ") foi desenvolvida por Bjarne Stroustrup como uma abordagem para fornecer funcionalidade orientada a objetos com uma sintaxe semelhante a C. [43] C ++ adiciona maior força de digitação, escopo e outras ferramentas úteis na programação orientada a objetos e permite a programação genérica por meio de modelos. Quase um superconjunto de C, C ++ agora suporta a maior parte de C, com algumas exceções .

Objective-C era originalmente uma camada muito "fina" no topo de C e permanece um superconjunto estrito de C que permite a programação orientada a objetos usando um paradigma de tipagem híbrido dinâmico / estático. Objective-C deriva sua sintaxe de C e Smalltalk : a sintaxe que envolve pré-processamento, expressões, declarações de funções e chamadas de funções é herdada de C, enquanto a sintaxe para recursos orientados a objetos foi originalmente tirada de Smalltalk.

Além de C ++ e Objective-C , Ch , Cilk e Unified Parallel C são quase superconjuntos de C.

Veja também

Notas

  1. ^ O código de exemplo original será compilado na maioria dos compiladores modernos que não estão no modo de conformidade padrão estrito, mas não está totalmente em conformidade com os requisitos do C89 ou C99. Na verdade, o C99 requer que uma mensagem de diagnóstico seja produzida.
  2. ^ Amainfunção na verdade tem dois argumentosint argcechar *argv[], respectivamente, que podem ser usados ​​para lidar com argumentos de linha de comando . O padrão ISO C (seção 5.1.2.2.1) requer que ambas as formasmainsejam suportadas, o que é um tratamento especial não concedido a qualquer outra função.

Referências

  1. ^ a b Kernighan, Brian W .; Ritchie, Dennis M. (fevereiro de 1978). A linguagem de programação C (1ª ed.). Englewood Cliffs, NJ : Prentice Hall . ISBN 978-0-13-110163-0.
  2. ^ Ritchie (1993) : "Thompson fez uma breve tentativa de produzir um sistema codificado em uma versão inicial de C - antes das estruturas - em 1972, mas desistiu do esforço."
  3. ^ Fruderica (13 de dezembro de 2020). "História de C" . O cppreference.com . Arquivado do original em 24 de outubro de 2020 . Recuperado em 24 de outubro de 2020 .
  4. ^ Ritchie (1993) : "O esquema de composição de tipo adotado por C tem uma dívida considerável com Algol 68, embora não tenha, talvez, emergido de uma forma que os adeptos de Algol aprovassem."
  5. ^ a b "Verilog HDL (e C)" (PDF) . A Escola de Pesquisa de Ciência da Computação da Australian National University. 3 de junho de 2010. Arquivado do original (PDF) em 6 de novembro de 2013 . Recuperado em 19 de agosto de 2013 . 1980:; Verilog introduzido pela primeira vez; Verilog inspirado na linguagem de programação C
  6. ^ a b c d e Ritchie (1993)
  7. ^ "Popularidade da linguagem de programação" . 2009. Arquivado do original em 16 de janeiro de 2009 . Recuperado em 16 de janeiro de 2009 .
  8. ^ "Índice da comunidade de programação TIOBE" . 2009. Arquivado do original em 4 de maio de 2009 . Recuperado em 6 de maio de 2009 .
  9. ^ a b "História de C" . en.cppreference.com . Arquivado do original em 29 de maio de 2018 . Recuperado em 28 de maio de 2018 .
  10. ^ "Índice TIOBE de outubro de 2021" . Recuperado em 7 de outubro de 2021 .
  11. ^ Ritchie, Dennis. "BCPL para B para C" . Arquivado do original em 12 de dezembro de 2019 . Recuperado em 10 de setembro de 2019 .
  12. ^ a b Johnson, SC ; Ritchie, DM (1978). "Portabilidade de programas C e o sistema UNIX". Bell System Tech. J . 57 (6): 2021–2048. CiteSeerX 10.1.1.138.35 . doi : 10.1002 / j.1538-7305.1978.tb02141.x . S2CID 17510065 .   (Observação: o PDF é uma digitalização OCR do original e contém uma renderização de "IBM 370" como "IBM 310".)
  13. ^ McIlroy, MD (1987). Um leitor Research Unix: trechos anotados do Manual do Programador, 1971–1986 (PDF) (Relatório técnico). CSTR. Bell Labs. p. 10. 139. Arquivado (PDF) do original em 11 de novembro de 2017 . Retirado em 1 de fevereiro de 2015 .
  14. ^ "Páginas de manual C". FreeBSD Miscellaneous Information Manual (FreeBSD 13.0 ed.). 30 de maio de 2011. Arquivado do original em 21 de janeiro de 2021 . Recuperado em 15 de janeiro de 2021 . [1] Arquivado em 21 de janeiro de 2021, na Wayback Machine
  15. ^ Kernighan, Brian W .; Ritchie, Dennis M. (março de 1988). A linguagem de programação C (2ª ed.). Englewood Cliffs, NJ : Prentice Hall . ISBN 978-0-13-110362-7.
  16. ^ Stroustrup, Bjarne (2002). Rivalidade entre irmãos: C e C ++ (PDF) (Relatório). AT&T Labs. Arquivado (PDF) do original em 24 de agosto de 2014 . Recuperado em 14 de abril de 2014 .
  17. ^ C Integridade . Organização Internacional para Padronização. 30 de março de 1995. Arquivado do original em 25 de julho de 2018 . Recuperado em 24 de julho de 2018 .
  18. ^ "JTC1 / SC22 / WG14 - C" . Página inicial . ISO / IEC. Arquivado do original em 12 de fevereiro de 2018 . Recuperado em 2 de junho de 2011 .
  19. ^ Andrew Binstock (12 de outubro de 2011). "Entrevista com Herb Sutter" . Dr. Dobbs . Arquivado do original em 2 de agosto de 2013 . Recuperado em 7 de setembro de 2013 .
  20. ^ "Cronograma C23 revisado WG 14 N 2759" (PDF) . www.open-std.org . Recuperado em 10 de outubro de 2021 .
  21. ^ "TR 18037: Embedded C" (PDF) . ISO / IEC. Arquivado (PDF) do original em 25 de fevereiro de 2021 . Recuperado em 26 de julho de 2011 .
  22. ^ Harbison, Samuel P .; Steele, Guy L. (2002). C: Um Manual de Referência (5ª ed.). Englewood Cliffs, NJ : Prentice Hall . ISBN 978-0-13-089592-9.Contém uma gramática BNF para C.
  23. ^ Kernighan & Ritchie (1996) , p. 192
  24. ^ Kernighan & Ritchie (1978) , p. 3
  25. ^ "Rascunho do Comitê da ISO / IEC 9899: 201x (ISO C11)" (PDF) . Arquivado (PDF) do original em 22 de dezembro de 2017 . Recuperado em 16 de setembro de 2011 .
  26. ^ Kernighan & Ritchie (1996) , pp. 192, 259.
  27. ^ "10 erros de programação comuns em C ++" . Cs.ucr.edu. Arquivado do original em 21 de outubro de 2008 . Recuperado em 26 de junho de 2009 .
  28. ^ Schultz, Thomas (2004). C e 8051 (3ª ed.). Otsego, MI: PageFree Publishing Inc. p. 20. ISBN 978-1-58961-237-2. Arquivado do original em 29 de julho de 2020 . Recuperado em 10 de fevereiro de 2012 .
  29. ^ Kernighan & Ritchie (1978) , p. 6
  30. ^ a b c d e f g Klemens, Ben (2013). 21st Century C . O'Reilly Media . ISBN 978-1-4493-2714-9.
  31. ^ Feuer, Alan R .; Gehani, Narain H. (março de 1982). "Comparação das Linguagens de Programação C e Pascal". Pesquisas de computação ACM . 14 (1): 73–92. doi : 10.1145 / 356869.356872 . S2CID 3136859 . 
  32. ^ Kernighan & Ritchie (1996) , p. 122
  33. ^ Por exemplo, gcc fornece _FORTIFY_SOURCE. "Recursos de segurança: Verificações de buffer de tempo de compilação (FORTIFY_SOURCE)" . fedoraproject.org. Arquivado do original em 7 de janeiro de 2007 . Recuperado em 5 de agosto de 2012 .
  34. ^ เอี่ยม สิริ วงศ์, โอภา ศ (2016). Programação com C . Bangkok, Tailândia: SE-EDUCATION PUBLIC COMPANY LIMITED. pp. 225–230. ISBN 978-616-08-2740-4.
  35. ^ Raymond, Eric S. (11 de outubro de 1996). The New Hacker's Dictionary (3ª ed.). MIT Press. p. 432. ISBN 978-0-262-68092-9. Arquivado do original em 12 de novembro de 2012 . Recuperado em 5 de agosto de 2012 .
  36. ^ "Página de manual para lint (seção 1 do freebsd)" . unix.com . 24 de maio de 2001 . Recuperado em 15 de julho de 2014 .
  37. ^ Dale, Nell B .; Weems, Chip (2014). Programação e resolução de problemas em C ++ (6ª ed.). Burlington, MA: Jones & Bartlett Learning. ISBN 978-1449694289. OCLC  894992484 .
  38. ^ Livro de origem do Dr. Dobb . EUA: Miller Freeman, Inc. de novembro a dezembro de 1995.
  39. ^ "Usando C para Programação CGI" . linuxjournal.com. 1 ° de março de 2005. Arquivado do original em 13 de fevereiro de 2010 . Recuperado em 4 de janeiro de 2010 .
  40. ^ McMillan, Robert (1º de agosto de 2013). "O Java está perdendo seu poder?" . Com fio . Arquivado do original em 15 de fevereiro de 2017 . Recuperado em 5 de março de 2017 .
  41. ^ O'Regan, Gerard (24 de setembro de 2015). Pilares da computação: um compêndio de empresas de tecnologia importantes e selecionadas . ISBN 978-3319214641. OCLC  922324121 .
  42. ^ Rauchwerger, Lawrence (2004). Linguagens e compiladores para computação paralela: 16º workshop internacional, LCPC 2003, College Station, TX, EUA, 2 a 4 de outubro de 2003: artigos revisados . Springer. ISBN 978-3540246442. OCLC  57965544 .
  43. ^ Stroustrup, Bjarne (1993). "A History of C ++: 1979-1991" (PDF) . Arquivado (PDF) do original em 2 de fevereiro de 2019 . Recuperado em 9 de junho de 2011 .

Fontes

Leitura adicional

Ligações externas