Por que as pessoas usam C se é tão perigoso?

132

Estou pensando em aprender C.

Mas por que as pessoas usam C (ou C ++) se podem ser usadas 'perigosamente'?

Por perigoso, quero dizer com ponteiros e outras coisas semelhantes.

Como a pergunta Estouro de pilha Por que a função gets é tão perigosa que não deve ser usada? . Por que os programadores não usam apenas Java ou Python ou outra linguagem compilada como o Visual Basic?

Tristan
fonte
152
Por que os chefs usam facas, se podem ser usadas 'perigosamente'?
oerkelens
78
Com grandes poderes vem grandes responsabilidades.
Pieter B
10
Joe Blow, muito pontificado?
Matthew James Briggs
4
Como "Back In The Day", quando C se tornou o idioma de escolha, era esperado que pudéssemos lidar com coisas assim, porque precisávamos. Os idiomas interpretados ou codificados por bytes eram muito lentos porque os processadores do dia eram muito mais lentos. (Hoje eu posso comprar um PC de mesa de gama baixa com uma CPU multinúcleo de 2+ GHz e 4 GB de memória da Dell por US $ 279. Você não tem idéia de como isso é absolutamente incrível para um cara como eu, para quem um PC de 4 MHz com 640 kilobytes de memória foi uma benção ...). Encare isso - a Lei de Moore venceu. Jogos. Sobre!
Bob Jarvis
6
@ Bob Jarvis: O jogo não acabou. Se você acha que seu PC de 2 + GHz e 4 GB - ou, nesse caso, seu cluster de várias centenas de PCs de 4 GHz com as mais recentes GPUs CUDA, ou o que seja - é rápido o suficiente, você simplesmente não está trabalhando em problemas suficientes :-)
jamesqf

Respostas:

246
  1. C é anterior a muitos dos outros idiomas em que você está pensando. Muito do que sabemos agora sobre como tornar a programação "mais segura" vem da experiência com linguagens como C.

  2. Muitos dos idiomas mais seguros lançados desde C dependem de um tempo de execução maior, de um conjunto de recursos mais complicado e / ou de uma máquina virtual para atingir seus objetivos. Como resultado, C permaneceu como um "menor denominador comum" entre todos os idiomas populares / populares.

    • C é uma linguagem muito mais fácil de implementar porque é relativamente pequena e tem mais probabilidade de ter um desempenho adequado, mesmo nos ambientes mais fracos, por isso muitos sistemas embarcados que precisam desenvolver seus próprios compiladores e outras ferramentas têm mais chances de fornecer um compilador funcional para C.

    • Como o C é muito pequeno e simples, outras linguagens de programação tendem a se comunicar usando uma API do tipo C. Essa é provavelmente a principal razão pela qual C nunca morrerá verdadeiramente, mesmo que a maioria de nós apenas interaja com ele por meio de invólucros.

  3. Muitas das linguagens "mais seguras" que tentam melhorar o C e o C ++ não estão tentando ser "linguagens de sistema" que oferecem controle quase total sobre o uso da memória e o comportamento em tempo de execução do seu programa. Embora seja verdade que hoje em dia, mais e mais aplicativos simplesmente não precisam desse nível de controle, sempre haverá um pequeno punhado de casos em que é necessário (principalmente dentro de máquinas virtuais e navegadores que implementam todas essas linguagens agradáveis ​​e seguras para o resto de nós).

    Hoje, existem algumas linguagens de programação de sistemas (Rust, Nim, D, ...) que são mais seguras que C ou C ++. Eles têm os benefícios da retrospectiva e percebem que, na maioria das vezes, esse controle fino não é necessário; portanto, oferecem uma interface geralmente segura com alguns ganchos / modos inseguros para os quais podemos mudar quando realmente necessário.

  4. Mesmo no C, aprendemos muitas regras e diretrizes que tendem a reduzir drasticamente o número de bugs insidiosos que aparecem na prática. Geralmente, é impossível obter o padrão para impor essas regras retroativamente, porque isso quebraria muito código existente, mas é comum usar avisos do compilador, linters e outras ferramentas de análise estática para detectar esses tipos de problemas facilmente evitáveis. O subconjunto de programas C que passam essas ferramentas com cores voadoras já é muito mais seguro do que "apenas C", e qualquer programador competente de C hoje em dia usará alguns deles.


Além disso, você nunca fará um concurso Java ofuscado tão divertido quanto o concurso C ofuscado .

Ixrec
fonte
7
"menor denominador comum" parece depreciativo. Eu diria que, diferentemente das muitas linguagens muito mais pesadas, o C não aplica uma tonelada de bagagem extra de que você não precisa e fornece uma base rápida em que você pode implementar o que precisa. É isso que você quis dizer?
underscore_d
9
"Você realmente não pode ter um sem o outro.": Na verdade, muitos novos idiomas (Rust, Nim, D, ...) tentam. Isso basicamente se resume a combinar um subconjunto "seguro" do idioma com algumas primitivas "inseguras" para quando esse nível de controle é absolutamente necessário. No entanto, todos eles se baseiam no conhecimento acumulado em C e C ++, portanto, talvez deva-se dizer que no momento em que C e C ++ foram desenvolvidos, você não podia ter um sem o outro e hoje em dia existe uma linguagem que tenta particionar seus bits "inseguros", mas ainda não os alcançaram.
Matthieu M.
6
1) não é um ponto válido! C recebeu recursos do Algol 68, que é uma linguagem "segura" nesse sentido; então os autores sabiam dessas línguas. Os outros pontos são ótimos.
reinierpost
4
@MatthieuM. Você também pode querer consultar o Microsoft Research. Eles produziram alguns SOs gerenciados na última década ou duas, incluindo alguns que são mais rápidos (completamente acidentalmente - o objetivo principal da maioria desses SOs de pesquisa é segurança, não velocidade) do que um SO não gerenciado equivalente para determinadas cargas de trabalho da vida real . A aceleração ocorre principalmente devido a restrições de segurança - a verificação executável estática e dinâmica permite otimizações que não estão disponíveis no código não gerenciado. Há um pouco para olhar, apesar de tudo, e as fontes estão incluídas;)
Luaan
3
@Luaan: Midori parece tão incrível; Estou sempre ansioso pelos artigos do blog de Joe.
precisa
41

Primeiro, C é uma linguagem de programação de sistemas. Portanto, por exemplo, se você escrever uma máquina virtual Java ou um interpretador Python, precisará de uma linguagem de programação de sistemas para gravá-los.

Segundo, C fornece desempenho que linguagens como Java e Python não. Normalmente, a computação de alto desempenho em Java e Python usará bibliotecas escritas em uma linguagem de alto desempenho como C para fazer o trabalho pesado.

Terceiro, C tem uma área de cobertura muito menor do que linguagens como Java e Python. Isso o torna utilizável para sistemas embarcados, que podem não ter os recursos necessários para suportar os grandes ambientes de tempo de execução e as demandas de memória de linguagens como Java e Python.


Uma "linguagem de programação de sistemas" é uma linguagem adequada para a construção de sistemas de força industrial; como estão, Java e Python não são linguagens de programação de sistemas. "O que exatamente faz uma linguagem de programação de sistemas" está fora do escopo desta pergunta, mas uma linguagem de programação de sistemas precisa fornecer suporte para trabalhar com a plataforma subjacente.

Por outro lado (em resposta aos comentários), uma linguagem de programação de sistemas não precisa ser auto-hospedada. Esta questão surgiu porque a pergunta original pediu "por que as pessoas usam C", o primeiro comentário perguntou "por que você precisa de uma linguagem como C" quando você tem PyPy, e notei que PyPy é que de fato usar C. Assim, foi originalmente relevante para a pergunta, mas infelizmente (e de maneira confusa) a "hospedagem automática" não é realmente relevante para esta resposta. Me desculpe, eu trouxe isso à tona.

Portanto, resumindo: Java e Python não são adequados à programação de sistemas, não porque suas implementações principais são interpretadas ou porque implementações compiladas nativamente não são auto-hospedadas, mas porque não fornecem o suporte necessário para trabalhar com a plataforma subjacente.

tempestade
fonte
19
"se você escrever uma máquina virtual Java ou um intérprete Python, precisará de uma linguagem de programação de sistemas para escrevê-los." Uh? Como você explica o PyPy? Por que você precisaria de uma linguagem como C para escrever um compilador, um intérprete ou uma máquina virtual?
Vincent Savard
10
Eu acredito que você afirmou que precisa de uma linguagem de programação do sistema para escrever uma máquina virtual Java ou um interpretador Python quando disse "se você escrever uma máquina virtual Java ou um interpretador Python, precisará de uma linguagem de programação do sistema para escrevê-los". Se o PyPy não o satisfizer, você também poderá procurar qualquer intérprete ou compilador escrito em Haskell. Ou, na verdade, basta adicionar uma referência que suporte sua reivindicação.
Vincent Savard
16
Mesmo se houver tartarugas, algo como o PyPy não poderia existir sem um intérprete do Python escrito em outra linguagem.
Blrfl
18
@ Birfl Mas isso não significa muito. C não poderia ter sido gravado sem um compilador de montagem e você não pode escrever uma montagem sem o hardware que o implementa.
gardenhead
11
Se o PyPy não é uma "linguagem de programação de sistemas" porque um compilador C está envolvido em algum lugar, C não é uma linguagem de programação de sistemas porque um montador é usado em algum lugar. Na verdade, não é popular traduzir C para outro idioma hoje em dia? por exemplo, LLVM
30

Lamento adicionar mais uma resposta, mas acho que nenhuma das respostas existentes aborda diretamente sua primeira frase, afirmando:

'Estou pensando em aprender C'

Por quê? Deseja fazer o tipo de coisa que C normalmente é usada atualmente (por exemplo, drivers de dispositivo, VMs, mecanismos de jogos, bibliotecas de mídia, sistemas incorporados, kernels de SO)?

Se sim, então sim, com certeza aprenda C ou C ++, dependendo de quem você está interessado. Deseja aprender para ter uma compreensão mais profunda do que sua linguagem de alto nível está fazendo?

Você então menciona as preocupações de segurança. Você não precisa necessariamente de um entendimento profundo do C seguro para fazer o último, da mesma maneira que um exemplo de código em uma linguagem de nível superior pode fornecer a essência sem estar pronto para a produção.

Escreva um código C para entender o essencial. Em seguida, coloque-o de volta na prateleira. Não se preocupe muito com segurança, a menos que queira escrever o código C de produção .

Jared Smith
fonte
2
Ótimo trabalho respondendo ao que parece ser a verdadeira questão! Uma ótima maneira de apreciar C / C ++ e linguagens "mais seguras" para tudo o que realmente são é tentar escrever algo como um simples mecanismo de banco de dados. Você terá uma boa ideia de cada uma das abordagens que tentar e verá aonde isso o leva. Você verá o que parece natural em ambos e descobrirá onde a abordagem natural falha (por exemplo, é muito fácil "serializar" dados brutos em C - basta escrever os dados !; mas o resultado não é portátil, por isso pode ser de uso limitado). Entender a segurança é complicado, porque a maioria dos problemas pode ser difícil de encontrar.
Luaan 8/06/16
1
@Luaan exatamente, aprender a copiar uma string usando ponteiros dá a você a ideia de que aprender com segurança é outro nível e, dependendo dos objetivos de alguém, talvez desnecessário.
Jared Smith
2
Esta não era realmente a questão. Mas foi útil para fazer uma dissisão. Eu decidi fazer isso. Estou disposto a aprender mais sobre o funcionamento interno de tudo o que é construído. E eu apenas gosto de programação. Dessa forma, espero entender melhor o funcionamento interno dos computadores. É só por diversão.
Tristan
10
Eu discordo da última frase. Aprenda como fazer isso antes de desenvolver maus hábitos.
glglgl
2
@glglgl IDK, se eu ler (ou escrever) um trecho de JavaScript na Web, o faço com o entendimento de que não está pronto para produção: não terá manipulação de exceção, pode ser O (n ^ 2), etc. Nenhum disso é necessário para entender o ponto. Tudo isso é necessário para o código de produção. Por que isso é diferente? Posso escrever C ingênuo para minha própria edificação, enquanto entendo intelectualmente que, se quisesse divulgá-lo, precisaria fazer muito mais trabalho.
Jared Smith
14

Esta é uma pergunta ENORME com toneladas de respostas, mas a versão curta é que cada linguagem de programação é especializada para diferentes situações. Por exemplo, JavaScript para web, C para itens de baixo nível, C # para qualquer coisa do Windows etc. É útil saber o que você deseja fazer depois de conhecer a programação para decidir qual linguagem de programação escolher.

Para abordar seu último ponto, por que o C / C ++ sobre Java / Python, muitas vezes se resume à velocidade. Eu faço jogos, e o Java / C # está apenas recentemente atingindo velocidades que são boas o suficiente para os jogos rodarem. Afinal, se você deseja que seu jogo seja executado a 60 quadros por segundo e você quer muito (renderização é particularmente caro), é necessário que o código seja executado o mais rápido possível. Python / Java / C # / Muitos outros executam "intérpretes", uma camada extra de software que lida com todas as coisas tediosas que o C / C ++ não faz, como gerenciar memória e coleta de lixo. Essa sobrecarga extra torna as coisas mais lentas, então quase todos os jogos grandes que você vê foram feitos (nos últimos 10 anos, pelo menos) em C ou C ++. Existem exceções: o mecanismo de jogo Unity usa C # * e o Minecraft usa Java, mas são a exceção, não a regra. Em geral,

* Mesmo o Unity não é apenas C #, grandes pedaços dele são C ++ e você apenas usa C # para o código do jogo.

EDITAR Para responder a alguns dos comentários que apareceram depois que eu postei isso: Talvez eu estivesse simplificando demais, estava apenas dando uma imagem geral. Com a programação, a resposta nunca é simples. Existem intérpretes para C, o Javascript pode ser executado fora do navegador e o C # pode ser executado em praticamente qualquer coisa, graças ao Mono. Diferentes linguagens de programação são especializadas para domínios diferentes, mas algum programador em algum lugar provavelmente descobriu como executar qualquer linguagem em qualquer contexto. Como o OP parecia não conhecer muita programação (suposição da minha parte, desculpe se estou errado), eu estava tentando manter minha resposta simples.

Quanto aos comentários sobre o C # ser quase tão rápido quanto o C ++, a palavra-chave existe quase. Quando eu estava na faculdade, visitamos muitas empresas de jogos, e meu professor (que nos incentivou a deixar o C # e entrar no C ++ o ano inteiro) perguntou aos programadores de todas as empresas que estudamos o porquê do C ++ sobre C # e de todos. disse que C # é muito lento. Em geral, ele é executado rapidamente, mas o coletor de lixo pode prejudicar o desempenho porque você não pode controlar quando é executado e tem o direito de ignorá-lo se não quiser executar quando você recomenda. Se você precisa de algo com alto desempenho, não quer algo tão imprevisível quanto isso.

Para responder ao meu comentário "apenas atingindo velocidades", sim, grande parte da velocidade do C # vem de um hardware melhor, mas como a estrutura .NET e o compilador C # foram aprimorados, houve algumas acelerações por lá.

Sobre o comentário "os jogos são escritos no mesmo idioma que o mecanismo", depende. Alguns são, mas muitos são escritos em um híbrido de idiomas. O Unreal pode executar UnrealScript e C ++, o Unity usa C # Javascript e Boo, muitos outros mecanismos escritos em C ou C ++ usam Python ou Lua como linguagens de script. Não há uma resposta simples lá.

E só porque me incomodou em ler "quem se importa se o seu jogo roda a 200fps ou 120fps", se o seu jogo está rodando acima de 60fps, você provavelmente está perdendo tempo na CPU, já que o monitor médio nem mesmo atualiza velozes. Alguns mais sofisticados e os mais novos, mas ainda não é padrão (ainda ...).

E sobre a observação "ignorar décadas de tecnologia", ainda estou no início dos meus 20 anos; portanto, quando estou extrapolando para trás, estou ecoando o que os programadores mais velhos e mais experientes me disseram. Obviamente, isso será contestado em um site como este, mas vale a pena considerar.

Cody
fonte
4
" C # para qualquer coisa Windows " - Ah, isso é uma falácia. E você até fornece um exemplo. Unidade. AFAIK Não está escrito, ele fornece API C # porque a linguagem é agradável e adaptável. É realmente bem desenhado. E eu gosto mais de c ++, mas o crédito deve ser concedido onde é devido. Talvez você tenha misturado C # com .NET. Eles saem juntos com bastante frequência.
Luk32
2
"Mesmo o Unity não é todo C #, grandes pedaços dele são C ++" E? Os jogos no Unity costumam usar o C # extensivamente e já existem há algum tempo. Sugerir que o C # está 'atingindo velocidades recentemente' precisa de mais contexto ou corre o risco de ficar cego para a tecnologia desta década.
NPSF3000
2
Quase todos os grandes jogos foram escritos no idioma do mecanismo usado: a quantidade de trabalho que seria necessário duplicar era tão grande que nenhuma outra consideração técnica sequer valeu a pena levar em consideração. A renderização é realmente cara, mas hoje em dia está tudo escrito em shaders e a linguagem do loop lógico é irrelevante.
Peter Taylor
2
O C # sempre foi compilado pelo JIT (diferente do Java, onde seu comentário está correto) e era capaz de velocidades de execução muito semelhantes ao C ++ desde o início, se você soubesse o que estava fazendo. Isso é 2003 - não é algo que eu consideraria recente. A velocidade bruta não é o principal problema dos jogos (especialmente com sombreadores programáveis ​​na GPU); há outras coisas que tornaram as linguagens como C # mais ou menos populares às vezes. Dois problemas principais são APIs (que são fortemente orientadas para C e a interface pode ser cara) e GC (principalmente para problemas de latência, não para taxa de transferência bruta).
Luaan 8/06/16
1
@gbjbaanb Não são apenas as CPUs que são mais rápidas - o importante é que C ++ e C tiveram décadas para aperfeiçoar seus compiladores e tempo de execução, enquanto o Java começou basicamente do zero (sendo projetado principalmente como uma plataforma multiplataforma). À medida que a VM melhorava (por exemplo, a troca de intérprete para um compilador JIT, aprimorava o GC ...), o desempenho dos aplicativos Java também aumentava. Muito do que o C / C ++ ainda possui está na abordagem "vamos torcer para que nada quebre" - evitando muitas verificações que são consideradas "desnecessárias". Mas ainda é um enorme devorador de memória - na verdade, melhorias para o uso da CPU muitas vezes significava o desempenho da memória pior :)
Luaan
13

É engraçado você afirmar que C é inseguro porque "possui indicadores". O oposto é verdadeiro: Java e C # têm praticamente apenas ponteiros (para tipos não nativos). O erro mais comum em Java é provavelmente a exceção do ponteiro nulo (consulte https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare ). O segundo erro mais comum é provavelmente manter referências ocultas a objetos não utilizados (por exemplo, diálogos fechados não são descartados) que, portanto, não podem ser liberados, levando a programas de longa duração com uma pegada de memória cada vez maior.

Existem dois mecanismos básicos que tornam C # e Java mais seguros e de duas maneiras diferentes:

  • A coleta de lixo torna menos provável que o programa tente acessar objetos descartados. Isso torna menos provável que o programa termine inesperadamente. Ao contrário de C, Java e C #, por padrão, alocam dados não nativos dinamicamente. Isso torna a lógica do programa realmente mais complexa, mas a coleta de lixo interna - a um custo - assume a parte mais difícil.

Os ponteiros inteligentes recentes do C ++ facilitam esse trabalho para os programadores.

  • Java e C # compilam para um código intermediário que é interpretado / executado por um tempo de execução elaborado. Isso adiciona um nível de segurança porque o tempo de execução pode detectar atividades ilícitas de um programa. Mesmo que o programa seja codificado de maneira insegura (o que é possível nos dois idiomas), o respectivo tempo de execução, em teoria, impede a "invasão" do sistema.
    O tempo de execução não protege contra, por exemplo, tentativas de saturação de buffer, mas, em teoria, não permite explorações de tais programas. Com C e C ++, por outro lado, o programador precisa codificar com segurança para evitar explorações. Isso geralmente não é alcançado imediatamente, mas precisa de revisões e iterações.

Vale ressaltar, porém, que o tempo de execução elaborado também é um risco à segurança. Parece-me que a Oracle está atualizando a JVM a cada duas semanas devido a problemas de segurança recém-descobertos. Obviamente, é muito mais difícil verificar a JVM do que um único programa.

Portanto, a segurança de um tempo de execução elaborado é ambígua e enganosa: seu programa C médio pode, com revisões e iterações, ser razoavelmente seguro. Seu programa Java médio é tão seguro quanto a JVM; isto é, não realmente. Nunca.

O artigo sobre o gets()qual você vincula reflete as decisões históricas da biblioteca que seriam tomadas de maneira diferente hoje, não a linguagem principal.

Peter A. Schneider
fonte
3
Penso que o objetivo do autor original é que, em C, você é capaz de executar ações desmarcadas nesses indicadores. Em java, você recebe uma boa exceção imediatamente - em C, você pode não perceber que está lendo um local inválido até que o estado do seu aplicativo esteja corrompido.
Sam Dufel
1
Além disso, stackoverflow.com/questions/57483/… - seria mais preciso dizer que java "praticamente apenas faz referência".
Sam Dufel
4
Eu já vi todos os tipos de erros interessantes resultantes de tentativas de evitar indicadores explícitos. Geralmente, a questão fundamental é a confusão entre cópia e referência. Em C, se eu passar um ponteiro para alguma coisa, você sabe que modificá-la afetará o original. Algumas das tentativas de evitar apontadores ofuscam essa distinção, levando a um labirinto de cópias profundas, cópias rasas e confusão geral.
Arlie Stephens
Afirmar que a JVM da Oracle é péssima (do ponto de vista da hemorragia de vulnerabilidades de segurança exploráveis) e, portanto, os tempos de execução das linguagens gerenciadas em geral introduzem mais preocupações de segurança do que o uso de uma linguagem gerenciada evita é como dizer que o Adobe Flash é horrível como fonte de insegurança e programa que a reprodução de vídeo e animação de um site deve ser inerentemente ridiculamente insegura. Nem todos os tempos de execução do Java são tão ruins quanto a abominação da JVM da Oracle / Sun nos anos 90, e nem todas as linguagens gerenciadas são Java. (Bem, obviamente.)
informou
@halfinformed Well; Eu estava dizendo que um programa é tão seguro quanto seu tempo de execução e que o programa "médio" (leia-se: small-ish) pode ser feito com mais esforço do que qualquer tempo de execução grande, como um interpretador de código de bytes. Essa afirmação parece inegável. Se um determinado programa independente ou um determinado tempo de execução é mais ou menos seguro que o outro depende de sua respectiva complexidade e qualidade de design, codificação e manutenção. Por exemplo, eu não diria que o sendmail é mais seguro que o Java VM da Oracle; mas qmail pode ser.
Peter A. Schneider
10

Como a "segurança" custa velocidade, os idiomas "mais seguros" têm desempenho mais lento.

Você pergunta por que usar uma linguagem "perigosa" como C ou C ++, alguém escreveu um driver de vídeo ou algo semelhante em Python ou Java, etc., e ver como você se sente sobre "segurança" :)

Sério, porém, você deve estar o mais próximo possível da memória principal da máquina para poder manipular pixels, registros, etc ... Java ou Python não podem fazer isso com qualquer tipo de velocidade digna de desempenho ... C e C ++ permitem que você faça isso através de ponteiros e similares ...

Wintermut3
fonte
20
Em geral, não é verdade que a segurança custa velocidade . Os idiomas disponíveis mais seguros realizam a maioria das verificações em tempo de compilação. O'Caml, Ada, Haskell e Rust não ficam muito atrás de C em termos de velocidade média de execução. O que eles não costumam incorrer em uma sobrecarga significativa no tamanho do programa, a eficiência da memória, latência e, obviamente, o tempo de compilação. E, sim, eles têm dificuldades com coisas próximas ao metal. Mas isso não é realmente um problema de velocidade.
usar o seguinte código
6
Além disso, C não faz o que você pensa que faz. C é uma máquina abstrata . Não oferece acesso direto a nada - isso é uma coisa boa. Você não pode nem olhar para a montagem moderna para ver quanto C está escondendo de você - a montagem moderna (por exemplo, TASM) teria sido considerada uma linguagem de alto nível quando C foi desenvolvido. Ficaria muito feliz se alguém escrevesse drivers em uma linguagem "segura", obrigado - isso ajudaria bastante a evitar muitos BSODs e congelamentos, sem mencionar brechas de segurança :) E o mais importante, existem linguagens de sistema muito mais seguras que C.
Luaan 8/16/16
3
@Wintermute Você realmente deseja consultar o Rust antes de fazer comentários sobre como os recursos de segurança necessariamente custam velocidade. Inferno, o sistema do tipo de baixo nível de C inibe muitas otimizações muito úteis que os compiladores poderiam fazer (principalmente quando se considera que praticamente nenhum projeto c grande consegue evitar não violar aliasing estrito em algum lugar ).
Voo
7
@ Wintermute Sim, o mito de que você não pode tornar C / C ++ mais seguro sem introduzir uma sobrecarga de desempenho é muito persistente, e é por isso que eu levo isso bastante a sério (existem algumas áreas em que isso certamente é verdadeiro [verificação de limites]). Agora, por que Rust não é mais difundido? História e complexidade. O Rust ainda é relativamente novo e muitos dos maiores sistemas escritos em C existiam antes de o Rust ser inventado - você não reescreveu um milhão de LOC em um novo idioma, mesmo que fosse muito mais seguro. Todos os programadores e seus cães também conhecem C, Rust? Boa sorte para encontrar pessoas suficientes.
Voo
3
@Voo Dogs fazendo C? ... não é de admirar que eu tenha visto tanto código ruim por aí ... j / k Ponto tomado sobre o Rust (eu apenas baixei e instalei, para que você possa ter outro convertido a adicionar) BTW em relação para Rust fazendo certo ... eu poderia fazer o mesmo augment para "D" :)
Wintermut3
9

Além de tudo acima, também há um caso de uso bastante comum, que está usando C como uma biblioteca comum para outros idiomas.

Basicamente, quase todos os idiomas têm uma interface API para C.

Exemplo simples, tente criar um aplicativo comum para Linux / IOS / Android / Windows. Além de todas as ferramentas disponíveis, acabamos fazendo uma biblioteca principal em C e alterando a GUI para cada ambiente, ou seja:

  • IOS: ObjectiveC pode usar bibliotecas C nativamente
  • Android: Java + JNI
  • Linux / Windows / MacOS: Com GTK / .Net, você pode usar bibliotecas nativas. Se você usa Python, Perl, Ruby, cada um deles possui interfaces de API nativas. (Java novamente com JNI).

Meus dois centavos,

Nito
fonte
Uma das razões pelas quais eu amo usar, digamos, o PHP, é porque quase todas as suas bibliotecas são, de fato, escritas em C - felizmente, ou o PHP seria insuportavelmente lento :) O PHP é ótimo para escrever código desleixado sem o medo de fazer qualquer coisa 'perigosa' (e é por isso que escrevo muito mais código PHP do que qualquer outra coisa - eu gosto de código desleixado!: D), mas é bom saber que, sob muitas dessas chamadas de função, há o bom e confiável bibliotecas C para dar-lhe algum aumento de desempenho ;-) por outro lado, escrever código desleixado em C é um grande não-não ...
Gwyneth Llewelyn
7

Uma dificuldade fundamental com C é que o nome é usado para descrever um número de dialetos com sintaxe idêntica, mas semântica muito diferente. Alguns dialetos são muito mais seguros que outros.

Em C, como originalmente projetado por Dennis Ritchie, as declarações C geralmente seriam mapeadas para as instruções da máquina de maneira previsível. Como o C podia funcionar em processadores que se comportavam de maneira diferente quando ocorriam coisas como estouro aritmético assinado, um programador que não sabia como uma máquina se comportaria em caso de estouro aritmético também não saberia o código C em execução nessa máquina, mas se se sabia que uma máquina se comporta de uma certa maneira (por exemplo, envolvente silencioso do complemento de dois em dois), as implementações nessa máquina normalmente fazem o mesmo. Uma das razões pelas quais C ganhou reputação de ser rápida foi que, nos casos em que os programadores sabiam que o comportamento natural de uma plataforma em cenários extremos atenderia às suas necessidades, não era necessário que o programador ou o compilador escrevesse o código para gerar esses cenários. .

Infelizmente, os escritores do compilador consideraram que, uma vez que o Padrão não impõe requisitos sobre o que as implementações devem fazer nesses casos (a negligência destinada a permitir implementações de hardware que podem não se comportar de maneira previsível), os compiladores devem se sentir à vontade para gerar código que nega as leis de tempo e causalidade.

Considere algo como:

int hey(int x)
{
   printf("%d", x);
   return x*10000;
}
void wow(int x)
{
  if (x < 1000000)
    printf("QUACK!");
  hey(x);    
}

A teoria do compilador hipermoderno (mas na moda) sugere que o compilador deve gerar "QUACK!" incondicionalmente, pois, em qualquer caso em que a condição fosse falsa, o programa acabaria invocando um comportamento indefinido executando uma multiplicação cujo resultado seria ignorado de qualquer maneira. Como o padrão permitiria que um compilador fizesse o que quisesse nesse caso, ele permite que o compilador produza "QUACK!".

Enquanto C costumava ser mais seguro que a linguagem assembly, ao usar compiladores hiper-modernos, o inverso é verdadeiro. Na linguagem assembly, o excesso de números inteiros pode fazer com que um cálculo produza resultados sem sentido, mas na maioria das plataformas essa será a extensão de seus efeitos. Se os resultados acabarem sendo ignorados, o excesso não importará. No C hiper-moderno, no entanto, mesmo o que normalmente seriam formas "benignas" de comportamento indefinido (como um excesso de número inteiro em um cálculo que acaba sendo ignorado) pode causar a execução arbitrária do programa.

supercat
fonte
1
mesmo em um compilador hipermoderno, C não verifica limites em matrizes. se o fizesse, isso não seria compatível com a definição do idioma. Eu uso esse fato algumas vezes para criar matrizes com um ponteiro adicional no meio da matriz para ter índices negativos.
Robert Bristow-johnson
1
Gostaria de ver evidências do seu exemplo produzindo "QUACK!" incondicionalmente. x certamente pode ser maior que 1000000 no ponto de comparação, e uma avaliação posterior que resultaria em estouro não impede isso. Além disso, se você tiver ativado o inlining, que permite remover a multiplicação excedente, seu argumento sobre as restrições implícitas de intervalo não será válido.
Graham
2
@ robertbristow-johnson: Na verdade, o Padrão diz explicitamente que, dado int arr[5][[5], por exemplo , uma tentativa de acesso arr[0][5]produzirá um comportamento indefinido. Essa regra possibilita a um compilador que recebe algo como arr[1][0]=3; arr[0][i]=6; arr[1][0]++;inferir que arr[1][0]será igual a 4, sem levar em consideração o valor de i.
Supercat 9/16
2
@ robertbristow-johnson: Mesmo que o compilador aloque matrizes dentro de uma estrutura sequencialmente sem lacunas, isso não garante que a indexação de uma das matrizes seja afetada por outra. Veja godbolt.org/g/Avt3KW para um exemplo de como o gcc tratará esse código.
supercat
1
@ robertbristow-johnson: comentei a assembléia para explicar o que está fazendo. O compilador vê que o código armazena 1 em s-> arr2 [0] e depois incrementa s-> arr2 [0], de modo que o gcc combina essas duas operações fazendo com que o código simplesmente armazene o valor 2, sem considerar a possibilidade de que a gravação interveniente para s-> arr1 [i] pode afetar o valor de s-> arr1 [0] (uma vez que, de acordo com a Norma, não pode).
precisa
5

Razões históricas. Não costumo escrever um código totalmente novo, principalmente para manter e estender o material antigo que está em execução há décadas. Estou feliz que seja C e não Fortran.

Fico irritado quando um aluno diz: "mas por que você faz esse X terrível quando pode estar fazendo Y?". Bem, X é o trabalho que tenho e paga as contas muito bem. Eu fiz Y de vez em quando e foi divertido, mas X é o que a maioria de nós faz.

RedSonja
fonte
5

O que é "perigoso"?

A alegação de que C é "perigoso" é um ponto de conversa frequente em guerras de chamas na linguagem (mais frequentemente em comparação com Java). No entanto, as evidências para esta alegação não são claras.

C é uma linguagem com um conjunto específico de recursos. Alguns desses recursos podem permitir certos tipos de erros que não são permitidos por outros tipos de idiomas (o risco do gerenciamento de memória de C geralmente é destacado). No entanto, isso não é o mesmo que argumentar que C é mais perigoso do que outras línguas em geral . Não conheço ninguém que forneça evidências convincentes sobre esse ponto.

Além disso, "perigoso" depende do contexto: o que você está tentando fazer e com que tipos de riscos está preocupado?

Em muitos contextos, eu consideraria C mais "perigoso" do que uma linguagem de alto nível, porque exige que você faça uma implementação mais manual da funcionalidade básica, aumentando o risco de erros. Por exemplo, fazer algum processamento básico de texto ou desenvolver um site em C normalmente seria idiota, porque outros idiomas têm recursos que facilitam muito isso.

No entanto, C e C ++ são amplamente utilizados para sistemas de missão crítica, porque uma linguagem menor com controle mais direto do hardward é considerada "mais segura" nesse contexto. De uma resposta muito boa de Stack Overflow :

Embora C e C ++ não tenham sido projetados especificamente para esse tipo de aplicativo, eles são amplamente utilizados para software embarcado e de segurança crítica por vários motivos. As principais propriedades da nota são o controle sobre o gerenciamento de memória (que permite evitar a coleta de lixo, por exemplo), bibliotecas simples e bem depuradas do tempo de execução do núcleo e suporte a ferramentas antigas. Muitas das cadeias de ferramentas de desenvolvimento incorporadas em uso atualmente foram desenvolvidas nas décadas de 1980 e 1990, quando essa era a tecnologia atual e vinha da cultura Unix que era predominante na época, portanto, essas ferramentas permanecem populares para esse tipo de trabalho.

Embora o código de gerenciamento de memória manual deva ser cuidadosamente verificado para evitar erros, ele permite um certo controle sobre os tempos de resposta do aplicativo que não estão disponíveis nos idiomas que dependem da coleta de lixo. As bibliotecas principais de tempo de execução das linguagens C e C ++ são relativamente simples, maduras e bem compreendidas, portanto estão entre as plataformas mais estáveis ​​disponíveis.

Comunidade
fonte
2
Eu diria que o C hipermoderno também é mais perigoso do que a linguagem assembly ou dialetos genuínos de baixo nível de C, que se comportam de maneira consistente como se traduzissem consistentemente operações C em operações de código de máquina, sem considerar casos extremos onde as operações naturais de código de máquina definiram um comportamento, mas o Padrão C não impõe requisitos. A abordagem hipermoderna, em que um excesso de número inteiro pode negar as regras de tempo e causalidade, parece muito menos passível de geração de código seguro.
Supercat
5

Para adicionar às respostas existentes, é bom dizer que você escolherá Python ou PHP para o seu projeto, por causa de sua relativa segurança. Mas alguém precisa implementar essas linguagens e, quando o fizerem, provavelmente o fará em C. (ou, bem, algo assim).

É por isso que as pessoas usam C - para criar as ferramentas menos perigosas que você deseja usar.

Raças de leveza em órbita
fonte
2

Permita-me reformular sua pergunta:

Estou pensando em aprender [ferramenta].

Mas por que as pessoas usam [ferramenta] (ou [ferramenta relacionada]) se [elas] podem ser usadas 'perigosamente'?

Qualquer ferramenta interessante pode ser usada perigosamente, incluindo linguagens de programação. Você aprende mais para poder fazer mais (e para que menos perigo seja criado ao usar a ferramenta). Em particular, você aprende a ferramenta para poder fazer o que é bom (e talvez reconheça quando essa ferramenta é a melhor ferramenta que você conhece).

Por exemplo, se você precisar colocar um orifício cilíndrico de 6 mm de diâmetro e 5 cm de profundidade em um bloco de madeira, uma broca é uma ferramenta muito melhor do que um analisador LALR. Se você sabe quais são essas duas ferramentas, você sabe qual é a ferramenta certa. Se você já sabe usar uma broca, voila !, buraco.

C é apenas mais uma ferramenta. É melhor para algumas tarefas do que para outras. As outras respostas aqui tratam disso. Se você aprender um pouco de C, reconhecerá quando é a ferramenta certa e quando não é.

Eric Towers
fonte
Esse monte de resposta é por que as perguntas são descartadas como "principalmente baseadas em opiniões". Não diga que C tem suas vantagens, diga o que são!
reinierpost
1

Estou pensando em aprender C

Não há razão específica para não aprender C, mas eu sugeriria C ++. Ele oferece muito do que C faz (já que C ++ é um superconjunto de C), com uma grande quantidade de "extras". Aprender C antes do C ++ é desnecessário - eles são linguagens efetivamente separadas.

Em outras palavras, se C fosse um conjunto de ferramentas para trabalhar madeira, provavelmente seria:

  • martelo
  • unhas
  • serra manual
  • furadeira
  • lixadeira de bloco
  • cinzel (talvez)

Você pode criar qualquer coisa com essas ferramentas - mas qualquer coisa legal potencialmente exige muito tempo e habilidade.

C ++ é a coleção de ferramentas elétricas em sua loja de ferragens local.

Se você seguir os recursos básicos da linguagem, o C ++ terá relativamente pouca curva de aprendizado adicional.

Mas por que as pessoas usam C (ou C ++) se podem ser usadas 'perigosamente'?

Porque algumas pessoas não querem móveis da IKEA. =)

Sério, embora muitas linguagens "mais altas" que C ou C ++ possam ter coisas que as tornam (potencialmente) "mais fáceis" de usar em certos aspectos, isso nem sempre é uma coisa boa. Se você não gosta da maneira como algo é feito ou o recurso não é fornecido, provavelmente não há muito o que fazer sobre isso. Por outro lado, C e C ++ fornecem recursos de linguagem de "baixo nível" suficientes (incluindo ponteiros) para que você possa acessar muitas coisas diretamente (especialmente hardware ou sistema operacional) ou construí-lo você mesmo, o que pode não ser possível em outros idiomas conforme implementado.

Mais especificamente, C possui o seguinte conjunto de recursos que o tornam desejável para muitos programadores:

  • Velocidade - Devido à sua relativa simplicidade e otimizações do compilador ao longo dos anos, é nativamente muito rápido. Além disso, muitas pessoas descobriram muitos atalhos para objetivos específicos ao usar o idioma, o que o torna potencialmente ainda mais rápido.
  • Tamanho - Por razões semelhantes às listadas para velocidade, os programas C podem ser muito pequenos (tanto em termos de tamanho de executável quanto de uso de memória), o que é desejável para ambientes com memória limitada (por exemplo, embutida ou móvel).
  • Compatibilidade - C já existe há muito tempo e todos têm ferramentas e bibliotecas para isso. A linguagem em si também não é exigente - ela espera que um processador execute instruções e memória para armazenar as coisas, e é isso.

    Além disso, há algo conhecido como ABI (Application Binary Interface) . Em resumo, é uma maneira de os programas se comunicarem no nível do código da máquina, o que pode ter vantagens sobre uma API (Application Programming Interface) . Enquanto outras linguagens como C ++ podem ter uma ABI, normalmente elas são menos uniformes (acordadas) que as de C, portanto, C é uma boa linguagem básica quando você deseja usar uma ABI para se comunicar com outro programa por algum motivo.

Por que os programadores não usam apenas Java ou Python ou outra linguagem compilada como o Visual Basic?

Eficiência (e ocasionalmente esquemas de gerenciamento de memória que não podem ser implementados sem acesso relativamente direto à memória).

O acesso direto à memória com ponteiros apresenta muitos truques legais (geralmente rápidos) quando você pode colocar suas patas sujas nas crianças e zeros nos cubos de memória diretamente e não ter que esperar que o professor velho distribua os brinquedos apenas na hora de brincar, pegue-os novamente.

Em suma, adicionar coisas potencialmente cria lag ou, de outra forma, introduz uma complexidade indesejada.

Com relação às linguagens de script e esse tipo, você precisa trabalhar duro para que as linguagens que exigem que os programas secundários sejam executadas com a mesma eficiência que o C (ou qualquer linguagem compilada) nativamente. A adição de um intérprete on-the-fly introduz inerentemente a possibilidade de menor velocidade de execução e maior uso de memória, porque você está adicionando outro programa ao mix. A eficiência de seus programas depende tanto da eficiência deste programa secundário quanto de quão bem (ruim =)) você escreveu o código do programa original. Sem mencionar que seu programa geralmente depende completamente do segundo programa para ser executado. Esse segundo programa não existe por algum motivo em um sistema específico? Código no go.

De fato, a introdução de algo "extra" potencialmente diminui ou complica seu código. Nas linguagens "sem ponteiros assustadores", você está sempre esperando que outros bits de código sejam limpos atrás de você ou, de outra forma, descubra maneiras "seguras" de fazer as coisas - porque seu programa ainda está fazendo as mesmas operações de acesso à memória que poderiam ser feitas com ponteiros. Você não é quem está lidando com isso (então você não pode f * ck, gênio = P).

Por perigoso, quero dizer com ponteiros e outras coisas semelhantes. [...] Como a pergunta Stack Overflow Por que a função gets é tão perigosa que não deve ser usada?

De acordo com a resposta aceita:

"Ele permaneceu uma parte oficial do idioma até o padrão ISO C de 1999, mas foi oficialmente removido pelo padrão de 2011. A maioria das implementações de C ainda o suporta, mas pelo menos o gcc emite um aviso para qualquer código que o use".

A noção de que, como algo pode ser feito em um idioma, deve ser feito é bobagem. Os idiomas têm falhas corrigidas. Por motivos de compatibilidade com código antigo, essa construção ainda pode ser usada. Mas não há nada (provável) forçando um programador a usar gets () e, de fato, esse comando foi essencialmente substituído por alternativas mais seguras.

Mais ao ponto, o problema com gets () não é um problema de ponteiro por si só. É um problema com um comando que não necessariamente sabe como usar a memória com segurança. Em um sentido abstrato, tudo isso é questão de ponteiro - ler e escrever coisas que você não deveria. Isso não é um problema com ponteiros; é um problema com a implementação do ponteiro.

Para esclarecer, os ponteiros não são perigosos até você acessar acidentalmente um local de memória que não pretendia. E mesmo assim, isso não garante que o seu computador derreta ou exploda. Na maioria dos casos, seu programa deixará de funcionar (corretamente).

Dito isto, como os ponteiros fornecem acesso aos locais da memória e porque os dados e o código executável existem juntos na memória, há um risco real de corrupção acidental o suficiente para que você queira gerenciar a memória corretamente.

Nesse ponto, como as operações de acesso à memória realmente diretas geralmente oferecem menos benefícios em geral do que poderiam ter anos atrás, mesmo linguagens sem coleta de lixo como o C ++ introduziram coisas como ponteiros inteligentes para ajudar a preencher a lacuna entre eficiência e segurança da memória.

Em resumo, há muito poucas razões para temer o ponteiro, desde que seja usado com segurança. Basta dar uma dica da versão de Steve "The Hunter Crocodile" Irwin, de South Park - não saia por aí enfiando o polegar nos buracos dos crocodilos .

Anaksunaman
fonte
2
Não concordo com a sugestão de aprender C ++ em vez de C. Escrever um bom C ++ é mais difícil do que escrever um bom C e ler C ++ é muito mais difícil do que ler C. Portanto, a curva de aprendizado do C ++ é muito mais acentuada. "C ++ é um super conjunto de C" É mais ou menos como dizer que botas são um superconjunto de chinelos. Eles têm vantagens e uso diferentes e cada um possui recursos que o outro não.
11556 Martellunev
"Escrever bom C ++ é mais difícil do que escrever bom C" - Absolutamente. =) "[R] ler C ++ é muito mais difícil do que ler C" - Qualquer programação avançada provavelmente é indistinguível de mágica ;-) Meus dois centavos são que isso depende muito mais do programador do que da linguagem, embora o C ++ não faça muito para ajudar a si próprio nesta categoria. "Portanto, a curva de aprendizado do C ++ é muito mais acentuada." - A longo prazo, sim. No curto prazo, menos (minha opinião). Curiosamente, a maioria dos cursos de idiomas básicos em C e C ++ provavelmente abrangerá aproximadamente os mesmos tipos gerais de material, exceto as classes para C ++.
Anaksunaman
2
"Eles têm vantagens e uso diferentes e cada um possui recursos que o outro não". - Como mencionado "Não há razão específica para não aprender C [.]" C é uma linguagem fina e eu mantenho isso. Se for adequado para OP ou qualquer outra pessoa, eu apoio totalmente o aprendizado. =)
Anaksunaman
Aprender C ensina como a máquina funciona (não totalmente, mas ainda um passo mais perto do metal). Essa é uma boa razão para aprender.
Agent_L 13/06
1

Como sempre, a linguagem de programação é apenas uma consequência da solução de problemas. Na verdade, você deve aprender não apenas C, mas muitas linguagens diferentes (e outras maneiras de programar um computador, sejam ferramentas da GUI ou intérpretes de comando) a ter uma caixa de ferramentas decente para usar na solução de problemas.

Às vezes, você descobrirá que um problema se presta bem a algo que está incluído nas bibliotecas padrão do Java; nesse caso, você pode escolher Java para aproveitar isso. Em outros casos, pode ser que você precise fazer algo muito mais simples no tempo de execução do .NET no Windows, portanto, você pode usar C # ou VB. Pode haver uma ferramenta gráfica ou script de comando que resolva o seu problema, então você pode usá-los. Talvez você precise escrever um aplicativo GUI em várias plataformas, o Java pode ser uma opção, considerando as bibliotecas incluídas no JDK, mas, novamente, uma plataforma de destino pode não ter um JRE, então talvez você escolha C e SDL (ou similar).

C tem uma posição importante neste conjunto de ferramentas, pois é geral, pequeno e rápido e também compila para o código de máquina. Também é suportado em todas as plataformas sob o sol (não sem recompilar no entanto).

Resumindo, você deve aprender quantas ferramentas, linguagens e paradigmas puder.

Afaste-se da mentalidade: "Sou um programador X" (X = C, C ++, Java, etc.)

Basta usar "Eu sou um programador".

Um programador resolve problemas e cria algoritmos instruindo as máquinas a executar a carga de trabalho. Fim da história. Isso é irrelevante para o idioma. Sua habilidade mais importante é a resolução de problemas e a quebra lógica de problemas estruturados; a habilidade / escolha de idioma SEMPRE é secundária e / ou uma consequência da natureza do problema.

Um caminho interessante se você estiver interessado em C é ampliar seu conjunto de habilidades com o Go. O Go é realmente um C melhorado, com coleta de lixo e interfaces, além de um bom modelo / canais de encadeamento, que também trazem muitos dos benefícios do C (como aritmética de ponteiro e compilação de código de máquina).

Richard Tyregrim
fonte
0

Depende do que você pretende fazer com isso. C foi projetado como um substituto para a linguagem assembly e é a linguagem de alto nível mais próxima da linguagem da máquina. Portanto, possui baixos custos indiretos em tamanho e desempenho e é adequado para programação de sistemas e outras tarefas que exigem uma área ocupada pequena e se aproximam do hardware subjacente.

Jonathan Rosenne
fonte
0

Quando você trabalha no nível de bits e bytes, da memória como uma coleta homogênea bruta de dados, como seria frequentemente necessário para implementar efetivamente os alocadores e estruturas de dados mais eficientes, não há segurança. A segurança é predominantemente um conceito forte relacionado ao tipo de dados e um alocador de memória não funciona com tipos de dados. Ele trabalha com bits e bytes para reunir esses mesmos bits e bytes, potencialmente representando um tipo de dado em um momento e outro posteriormente.

Não importa se você usa C ++ nesse caso. Você ainda estaria espalhando static_caststodo o código para transmitir a partir de void*ponteiros e ainda trabalhando com bits e bytes e apenas lidando com mais aborrecimentos relacionados a respeitar o sistema de tipos nesse contexto do que C, que tem um sistema de tipos muito mais simples, onde você está livre de memcpybits e bytes redor sem se preocupar com bulldozing sobre o sistema de tipo.

Na verdade, muitas vezes é mais difícil trabalhar em C ++, uma linguagem geral mais segura, em contextos de baixo nível de bits e bytes sem escrever código ainda mais perigoso do que você faria em C, já que você pode estar fazendo um bulldoze no sistema de tipos do C ++ e fazendo coisas como sobrescrevendo vptrs e não invocando construtores e destruidores de cópia em momentos apropriados. Se você dedicar um tempo adequado para respeitar esses tipos e usar a colocação de novos e chamar manualmente os dtors e assim por diante, será exposto ao mundo do tratamento de exceções em um contexto de nível muito baixo para que o RAII seja prático e alcance exceções. a segurança em um contexto de nível tão baixo é muito difícil (você precisa fingir que qualquer função pode lançar e capturar todas as possibilidades e reverter todos os efeitos colaterais como uma transação indivisível, como se nada tivesse acontecido). O código C pode frequentemente "

E seria impossível implementar esses alocadores em idiomas que não permitem que você seja "perigoso" aqui; você teria que se apoiar em qualquer alocador que eles fornecem (implementado provavelmente em C ou C ++) e espero que seja bom o suficiente para seus propósitos. E há quase sempre alocadores e estruturas de dados mais eficientes, mas menos gerais, adequados para seus propósitos específicos, mas muito mais restritos, pois são especificamente adaptados para seus propósitos.

A maioria das pessoas não precisa de C ou C ++, uma vez que pode simplesmente chamar código implementado originalmente em C ou C ++ ou possivelmente até montagem já implementada para eles. Muitos podem se beneficiar da inovação de alto nível, como montar um programa de imagem que apenas usa bibliotecas de funções de processamento de imagem existentes já implementadas em C, onde não estão inovando tanto no nível mais baixo de loop através de pixels individuais, mas talvez oferecendo uma interface de usuário muito amigável e um fluxo de trabalho nunca antes visto. Nesse caso, se o objetivo do software é apenas fazer chamadas de alto nível em bibliotecas de baixo nível ( "processe toda essa imagem para mim, não para cada pixel, faça alguma coisa" ), então pode ser uma otimização prematura. até tentar começar a escrever esse aplicativo em C.

Mas se você está fazendo algo novo em um nível baixo, onde ajuda a acessar dados de um nível mais baixo, como um novo filtro de imagem nunca visto antes, que é rápido o suficiente para trabalhar em vídeo HD em tempo real, geralmente é necessário obter um pouco perigoso.

É fácil tomar essas coisas como garantidas. Lembro-me de uma postagem no Facebook com alguém apontando como é possível criar um videogame 3D com Python, com a implicação de que linguagens de baixo nível estão se tornando obsoletas, e certamente era um jogo de aparência decente. Mas o Python estava fazendo chamadas de alto nível para as bibliotecas implementadas em C para fazer todo o trabalho pesado. Você não pode fazer o Unreal Engine 4 apenas fazendo chamadas de alto nível para as bibliotecas existentes. O Unreal Engine 4 éa biblioteca. Ele fez todos os tipos de coisas que nunca existiram em outras bibliotecas e mecanismos, desde a iluminação até o sistema de projeto nodal e como ele pode compilar e executar o código rapidamente. Se você deseja inovar no tipo de baixo nível de mecanismo / núcleo / kernel, precisa obter um nível baixo. Se todos os desenvolvedores de jogos mudassem para idiomas seguros de alto nível, não haveria o Unreal Engine 5, 6 ou 7. Provavelmente ainda haveria pessoas usando o Unreal Engine 4 décadas depois, porque você não pode inovar no nível necessário para vir com um mecanismo de última geração, fazendo apenas chamadas de alto nível para o antigo.


fonte