C é uma das línguas mais usadas no mundo. É responsável por uma grande proporção do código existente e continua a ser usado por uma grande quantidade de novos códigos. É amado por seus usuários, é tão amplamente portado que ser capaz de executar C é, para muitos, a definição informal de plataforma , e é elogiado por seus fãs por ser uma linguagem "pequena" com um conjunto relativamente limpo de recursos.
Então, onde estão todos os compiladores?
Na área de trabalho, existem (realisticamente) dois : GCC e Clang. Pensando nisso por alguns segundos, você provavelmente lembrará que a Intel também existe. Existem muitos outros, muito obscuros para o nome de uma pessoa comum e quase universalmente não se preocupando em oferecer suporte a uma versão recente do idioma (ou geralmente até um subconjunto de idiomas bem definido, apenas "um subconjunto"). Metade dos membros desta lista são notas de rodapé históricas; o restante é muito especializado e ainda não implementa a linguagem completa. Muito poucos realmente parecem ser de código aberto.
Scheme e Forth - outros pequenos idiomas que são amados por seus fãs - provavelmente têm mais compiladores do que usuários reais. Até mesmo algo como SML tem implementações mais "sérias" para escolher do que C. Considerando que o anúncio de um novo compilador C (inacabado) que visa a verificação realmente vê algumas respostas bastante negativas, e as implementações veteranas lutam para conseguir colaboradores suficientes para alcançar os C99
Por quê? A implementação de C é tão difícil? Não é C ++. Os usuários simplesmente têm uma ideia muito distorcida sobre em qual grupo de complexidade ele se enquadra (isto é, na verdade, é mais próximo do C ++ do que do Scheme)?
Respostas:
Hoje, você precisa de um compilador C real para ser um otimizador , principalmente porque C não é mais uma linguagem próxima ao hardware, porque os processadores atuais são incrivelmente complexos ( fora de ordem , em pipeline , superescalar , com caches complexos e TLB , portanto, necessitando de agendamento de instruções , etc ...). Os processadores x86 de hoje não são como os processadores i386 do século anterior, mesmo que ambos possam executar o mesmo código de máquina. Veja que o documento C não é um idioma de baixo nível (Seu computador não é um PDP-11 rápido) de David Chisnall.
Poucas pessoas estão usando compiladores C ingênuos e não otimizadores, como tinycc ou nwcc , pois eles produzem código que é várias vezes mais lento do que o que os compiladores otimizadores podem oferecer.
Codificar um compilador otimizador é difícil. Observe que o GCC e o Clang estão otimizando alguma representação de código "neutra no idioma de origem" (Gimple for GCC, LLVM for Clang). A complexidade de um bom compilador C não está na fase de análise!
Em particular, criar um compilador C ++ não é muito mais difícil do que criar um compilador C: analisar o C ++ e transformá-lo em alguma representação de código interno é complexo (porque a especificação do C ++ é complexa), mas é bem compreendido, mas as partes de otimização são ainda mais complexo (dentro do GCC: as otimizações de ponto intermediário, idioma de origem e processador de destino neutros, formam a maioria do compilador, com o restante sendo equilibrado entre front-ends para vários idiomas e back-ends para vários processadores). Portanto, a maioria dos compiladores C otimizadores também é capaz de compilar algumas outras linguagens, como C ++, Fortran, D, ... As partes específicas de C ++ do GCC são cerca de 20% do compilador ...
Além disso, C (ou C ++) é tão amplamente usado que as pessoas esperam que seu código seja compilável, mesmo quando ele não segue exatamente os padrões oficiais, que não definem com precisão a semântica da linguagem (para que cada compilador possa ter sua própria interpretação). ). Veja também o compilador C comprovado pelo CompCert e o analisador estático Frama-C , que se preocupam com a semântica mais formal de C.
E as otimizações são um fenômeno de cauda longa : implementar algumas otimizações simples é fácil, mas elas não tornarão um compilador competitivo! Você precisa implementar muitas otimizações diferentes, organizar e combiná-las de maneira inteligente, para obter um compilador do mundo real que seja competitivo. Em outras palavras, um compilador de otimização do mundo real precisa ser um software complexo. BTW, o GCC e o Clang / LLVM têm vários geradores de código C / C ++ especializados internos. E ambos são grandes animais (vários milhões de linhas de código-fonte, com uma taxa de crescimento de vários por cento ao ano) com uma grande comunidade de desenvolvedores (algumas centenas de pessoas, trabalhando principalmente em período integral ou pelo menos meio período).
Observe que não existe (até onde sei) compilador C multithread, mesmo que algumas partes de um compilador possam ser executadas em paralelo (por exemplo, otimização intra-processual, alocação de registro, programação de instruções ...). E a construção paralela com
make -j
nem sempre é suficiente (especialmente com LTO ).Além disso, é difícil obter recursos para codificar um compilador C do zero, e esse esforço precisa durar vários anos. Finalmente, a maioria dos compiladores C ou C ++ é software livre hoje (não há mais mercado para novos compiladores proprietários vendidos por startups) ou pelo menos são mercadorias monopolistas (como o Microsoft Visual C ++ ), e ser um software livre é quase necessário para compiladores ( porque precisam de contribuições de muitas organizações diferentes).
Eu ficaria muito satisfeito em conseguir financiamento para trabalhar em um compilador C do zero como software livre, mas não sou ingênuo o suficiente para acreditar que isso é possível hoje!
fonte
(there is no more a market for proprietary compilers
Diga isso para a equipe Visual Studio ...Gostaria de contestar sua suposição subjacente de que há apenas um pequeno número de implementações em C.
Eu nem conheço C, não uso C, não sou membro da comunidade C e, no entanto, conheço muito mais do que os poucos compiladores que você mencionou.
Em primeiro lugar, existe o compilador que provavelmente supera completamente o GCC e o Clang na área de trabalho: Microsoft Visual C. Apesar das incursões que o OSX e o Linux têm feito na área de trabalho, e a participação no mercado que iOS e Android "roubaram" longe dos antigos usuários de desktop tradicionais, o Windows ainda é o sistema operacional dominante na área de trabalho, e a maioria dos programas de desktop C do Windows provavelmente são compilados usando as ferramentas da Microsoft.
Tradicionalmente, todo fornecedor de SO e todo fornecedor de chips tinham seus próprios compiladores. A Microsoft, como fornecedor de SO, possui o Microsoft Visual C. A IBM, como fornecedor de SO e de chip, possui XLC (que é o compilador de sistema padrão para AIX e o compilador com o qual o AIX e o i / OS são compilados) . A Intel tem seu próprio compilador. Sun / Oracle tem seu próprio compilador no Sun Studio.
Depois, existem fornecedores de compiladores de alto desempenho, como o PathScale e o The Portland Group, cujos compiladores (e bibliotecas OpenMP) são usados para processamento de números.
A Digital Mars também ainda está no mercado. Acredito que Walter Bright tenha a distinção única de ser a única pessoa no planeta que conseguiu criar um compilador C ++ com qualidade de produção (principalmente) sozinho.
Por último, mas não menos importante, temos todos os compiladores proprietários para microcontroladores incorporados. Segundo o IIRC, há mais microcontroladores vendidos a cada ano do que as CPUs de desktop, celular, servidor, estação de trabalho e mainframe que foram vendidas em toda a história da computação combinada. Portanto, esses definitivamente não são produtos de nicho.
Uma menção honrosa é dada ao TruffleC , um intérprete C (!) Executado na JVM (!) Escrito usando a estrutura de intérpretes Truffle AST que é apenas 7% mais lenta que o GCC e o Clang (o que for mais rápido em um determinado parâmetro de referência) em todo o Computer Languages Benchmark Game, e mais rápido do que ambos nos microbenchmarks. Usando o TruffleC, a equipe do Truffle conseguiu que sua versão do JRuby + Truffle executasse extensões Ruby C mais rapidamente do que a implementação real do C Ruby!
Então, essas são 6 implementações, além das listadas, que eu posso citar de cabeça, sem nem mesmo saber nada sobre C.
fonte
Quantos compiladores você precisa?
Se eles tiverem conjuntos de recursos diferentes, você cria um problema de portabilidade. Se eles são comoditizados, você escolhe o "padrão" (GCC, Clang ou VS). Se você se preocupa com os últimos 5% de desempenho, tem uma referência.
Se você estiver trabalhando com linguagem de programação de maneira recreativa ou para fins de pesquisa, é provável que esteja em uma linguagem mais moderna. Daí a proliferação de compiladores de brinquedos para Scheme e ML. Embora o OCaml pareça estar recebendo alguma tração para usos não acadêmicos que não são de brinquedos.
Observe que isso varia muito de acordo com o idioma. Java possui essencialmente a cadeia de ferramentas Sun / Oracle e a GNU. O Python possui vários compiladores, nenhum dos quais é realmente respeitado em comparação com o intérprete padrão. O Rust and Go possui exatamente uma implementação cada. C # tem Microsoft e Mono.
fonte
1000 * 0
ainda é0
.int
, e exigirá que compiladores diferentes interpretem o mesmo código-fonte de maneiras muito diferentes.6g
/8g
/… toolchain e gccgo). Também costumava haver uma implementação comercial proprietária muito interessante chamada erGo, que era a) uma implementação nativa do Go no Windows em um momento em que nem o gccgo nem o compilador Go original funcionavam muito bem no Windows, b) uma empresa que aposta no Go há muito tempo antes mesmo de se tornar 1.0, e c) a primeira implementação do Go escrita em Go (gccgo e 6g / 8g são escritos em C). Tanto o projeto quanto a empresa desapareceram antes mesmo de sair do beta fechado.O C / C ++ é único entre as linguagens compiladas, pois possui três implementações principais de uma especificação comum.
Seguindo a regra de descartar qualquer coisa que não seja muito usada, todos os outros idiomas compilados têm de 0 a 1.
E acho que o javascript é a única razão pela qual você precisa especificar 'compilado'.
fonte
uint16_t a=48000u; unsigned uint32_t b=(a*a)/2;
como atribuindo aob
valor 8192. Alguns o definem como atribuindo 1152000000. Atualmente, ele é considerado um comportamento indefinido e provavelmente armazena 3299483648, mas não faz nenhuma promessa a esse respeito.2
ou2u
aparentemente./2u
? Estouro não assinado é definido (como módulo 2 ^ N para N definido pela implementação), mas a divisão não pode estourar.int
, mas cujo produto não se encaixaria nesse tipo. Coagir esse resultado a int não assinado provavelmente mudaria a interpretação do valor resultante, mas não negaria o Comportamento Indefinido do cálculo anterior.Então, qual é o seu idioma de destino?
Os compiladores SML geralmente têm como alvo C ou algo como LLVM (ou como visto no seu link, JVM ou JavaScript).
Se você está compilando C, não é porque está indo para a JVM. Você está indo para algo pior que C. Muito pior. E então você pode duplicar esse inferno menor várias vezes para todas as suas plataformas de destino.
E claro, C não é C ++, mas eu diria que é mais próximo de C ++ que de Scheme. Ele tem seu próprio subconjunto de maldade indefinida de comportamento (estou olhando para o tamanho de tipos embutidos). E se você estragar essas minúcias (ou fazê-lo "corretamente", mas inesperadamente), há décadas de código existente em sistemas vitais que lhe dirão o quão terrível você é. Se você estragar um compilador SML, ele simplesmente não funcionará - e alguém pode perceber. Algum dia.
fonte
int
ter 32 ou 64 bits, mas pode ser tão pequeno quanto 16 bits. Não é difícil produzir um número fora da faixa[−32767, +32767]
e oint
excesso é UB. Também háchar
/short
sendo promovidoint
ouunsigned int
dependendo de seint
pode representar todos os valores do tipo original, o que pode desencadear ainda mais uma conversão deint
paraunsigned int
se os operandos tivessem tipos diferentes e tivessem sido convertidos de maneira diferente, além de potencialmente outra conversão ao atribuir o resultado a uma variável .