É necessário seguir o padrão, adotar o padrão C para esse assunto?

17

Existem pessoas muito experientes no Stack Overflow que sempre falam sobre o padrão C. As pessoas parecem não gostar de soluções não portáteis, mesmo que funcionem para mim. Ok, entendo que o padrão precisa ser seguido, mas isso não compromete a criatividade do programador?

Quais são os benefícios concretos resultantes de seguir um padrão? Especialmente porque os compiladores podem implementar o padrão de maneira ligeiramente diferente.

0decimal0
fonte
7
Você poderia esclarecer o que você quer dizer com "o padrão"? Você quer dizer não reagir a um comportamento que não é definido pelo padrão? Ou não usando extensões / recursos do compilador? Ou convenções de estilo?
Ikh
1
@ikh Ele está adotando os padrões ISO C (C90, C99, C11).
Aseem Bansal
9
É o mesmo que dizer que escrever ou falar em inglês, usando gramática e vocabulário, prejudica sua criatividade. Certamente, as pessoas podem fazer coisas maravilhosas violando as regras, ao custo da coerência, mas você pode escrever milhões de livros criativos enquanto segue o "padrão" do inglês.
Avner Shahar-Kashtan
você pode adicionar um exemplo de "As pessoas parecem não gostar de soluções não portáteis, mesmo que funcionem para mim"?
BЈовић
1
@PHIfounder Só para endereço esse último caso, você pode omitir o retorno do principal, que é voltar implicitamente 0 :)
Daniel Gratzer

Respostas:

45

Existem algumas razões pelas quais seguir o padrão é uma coisa boa.

  1. Ser bloqueado em um compilador é uma droga. Você está completamente à mercê de um grupo de desenvolvedores com sua própria agenda. Obviamente, eles não querem pegar você ou algo assim, mas se o seu compilador começar a ficar com otimizações, novos recursos, correções de segurança etc., muito ruim; Você está preso. Em casos extremos, algumas empresas precisam começar a corrigir qualquer ferramenta da qual se tornem dependentes. É um enorme desperdício de tempo e dinheiro quando existem outras ferramentas de trabalho por aí.

  2. Ficar trancado em uma plataforma é mais difícil. Se você está desenvolvendo software no Linux e deseja mudar para o Windows porque percebe que o seu mercado está realmente lá, você terá muito tempo mudando todos os hacks não portáteis que você possui no seu código para ter um bom desempenho com o GCC e o MSVC. Se você tem várias peças do seu design principal baseadas em algo assim, boa sorte!

  3. Alterações incompatíveis com versões anteriores são as mais difíceis. O padrão nunca quebrará seu código (Ignorar python). Alguns gravadores de compiladores aleatórios, no entanto, podem decidir que realmente esse complemento específico da implementação não vale a pena e o deixa cair. Se você confiar nele, ficará preso na versão antiga desatualizada em que foi a última.

Portanto, a mensagem principal aqui, manter o padrão torna você mais flexível . Você tem um idioma mais limitado, mas você tem mais

  • Bibliotecas
  • Suporte (as pessoas conhecem o padrão, nem todos os intrincados truques específicos do compilador)
  • Plataformas disponíveis
  • Ferramentas maduras
  • Segurança (prova futura)

É um equilíbrio delicado, mas ignorar completamente o padrão é definitivamente um erro. Costumo organizar meu código C para confiar em abstrações que podem ser implementadas de maneira não portátil, mas que posso portar de forma transparente sem alterar tudo o que depende da abstração.

Daniel Gratzer
fonte
+1 bastante justo :), obrigado ... Fiquei seriamente confuso com o modo como os compiladores se desviaram um pouco dos padrões e me fez sentir cético em segui-lo estritamente, precisava conhecer os prós e contras dele e você os identificou claramente.
usar o seguinte comando
6
O comportamento indefinido provavelmente também é uma porcaria. Com c, é muito fácil se aventurar no UB se você não seguir o padrão de perto.
CodesInChaos
@CodesInChaos Acordado, comportamento indefinido é grande, por um lado, uma vez que permite algumas otimizações loucos, mas por outro depuração-lo ...
Daniel Gratzer
6

O padrão é uma espécie de "contrato" entre você e seu compilador que define o significado dos seus programas. Como programadores, geralmente temos um certo modelo mental de como a linguagem funciona, e esse modelo mental geralmente está em desacordo com o padrão. (Por exemplo, os programadores C geralmente pensam em um ponteiro como "um número inteiro que denota um endereço de memória" e, portanto, assumem que é seguro executar qualquer aritmética / conversões / manipulações em ponteiros que alguém possa executar com um número inteiro que denota uma memória Essa suposição não concorda com o padrão; na verdade, impõe restrições muito rígidas ao que você pode fazer com os ponteiros.)

Então, qual é a vantagem de seguir o padrão, e não o seu próprio modelo mental?

Simplificando, é que o padrão está correto e seu próprio modelo mental está errado. Seu modelo mental é geralmente uma visão simplificada de como as coisas funcionam em seu próprio sistema, em casos comuns, com todas as otimizações do compilador desativadas; Os fornecedores de compiladores geralmente não fazem um esforço para se adaptar a ele, especialmente quando se trata de otimizações. (Se você não aguentar o final do contrato, não poderá esperar nenhum comportamento específico do compilador: entrada de lixo, saída de lixo.)

As pessoas parecem não gostar de soluções não portáteis, mesmo que funcionem para mim.

Talvez seja melhor dizer "mesmo que eles pareçam funcionar para mim". A menos que o seu compilador documente especificamente que um determinado comportamento funcionará (ou seja: a menos que você esteja usando um padrão enriquecido, consistindo na documentação padrão apropriada do compilador), você não sabe que ele realmente funciona ou que é realmente confiável. Por exemplo, o excesso de número inteiro assinado normalmente resulta em agrupamento em muitos sistemas ( INT_MAX+1geralmente é o caso INT_MIN) - exceto que os compiladores "sabem" que a aritmética de número inteiro assinado nunca transborda em um programa C (correto) e geralmente realiza otimizações surpreendentes com base nisso " conhecimento".

ruakh
fonte
1
Você pode compilar com -fwrapve, em seguida, usar um idioma não padrão levemente diferente, no qual a aritmética inteira assinada sempre envolve.
user253751
@immibis: Quando o C89 foi escrito, de acordo com seu documento de justificativa, a maioria dos compiladores contemporâneos definiu a semântica de empacotamento silencioso para o excesso de números inteiros. Em muitos casos, ter algum tipo de garantia sobre o que acontece em caso de estouro de número inteiro pode permitir que o código seja mais eficiente do que seria possível sem essas garantias, especialmente se as garantias não chegarem ao ponto de exigir um comportamento preciso de empacotamento. o comportamento de quebra automática pode ser emulado usando matemática não assinada, mas a semântica mais frouxa, mas ainda adequada para atender aos requisitos, pode permitir um código mais eficiente].
Supercat
@immibis: É uma pena que os revisionistas tenham conseguido convencer as pessoas de que os comportamentos implementados quase por unanimidade entre os compiladores de determinadas plataformas (ou, em alguns casos, 100% por unanimidade) nunca foram "padrão" nessas plataformas, pois em muitos casos os a perda de eficiência resultante da necessidade de evitar tais comportamentos não será recuperada por quaisquer "otimizações" que um compilador conseguiu alcançar ao revogá-las.
Supercat
4

Entendo que o padrão precisa ser seguido, mas isso não compromete a criatividade do programador? ainda existem algumas diferenças na maneira como diferentes compiladores seguem os padrões. Por exemplo, posso escrever um código que funcione, muito bom em desempenho e velocidade, isto é, tudo o que importa, mas ainda assim não necessariamente siga rigorosamente os padrões.

Não. O padrão informa o que é permitido fazer. Se não for especificado, você estará em um território de comportamento indefinido e todas as apostas serão desativadas - o programa é livre para fazer qualquer coisa.


Como você mencionou um exemplo específico de void main()vs int main(), posso melhorar minha resposta.

void main()não é uma declaração padrão da função principal. Pode funcionar em alguns compiladores por meio de extensões, mas depende da implementação. Mesmo que funcione, você deve verificar se faz o que deseja. O problema é que os desenvolvedores do compilador podem decidir remover void main()com a próxima versão do compilador, quebrando o aplicativo.

Por outro lado, o padrão define claramente a assinatura de main como int main()e indica o que deve fazer.


Por outro lado, há coisas não definidas no padrão. Então, outro padrão pode ser aplicado (como, por exemplo, POSIX). O melhor exemplo pode ser a implementação de threads no c ++ 03, já que os programas padrão do c ++ 03 eram 1-threaded. Nesse caso, você é forçado a usar a biblioteca dependente da plataforma ou algo parecido com impulso .

BЈовић
fonte
4
Tudo o que um compilador faz que não é padrão não é um comportamento indefinido, as extensões do compilador são bem definidas no sentido de serem determinísticas e deliberadas. UB não é.
Daniel Gratzer
@jozefg Do jeito que foi solicitado - é óbvio que o OP pensou na maneira de implementar o UB. Por exemplo, os threads não foram definidos no c ++ 03.
BЈовић
1
@deworde: O comentário foi removido da resposta.
Kevin - Restabelece Monica
@jozefg Se um compilador em particular sempre envolve números inteiros assinados, ele pode ser considerado uma extensão de idioma não documentada. (Claro que, sendo os meios indocumentados você não tem garantias sobre eles não remover a extensão)
user253751
-6

Não siga as regras, se o seu projeto for sobre projetos especiais, por exemplo, um projeto de governo ou exército, mas você precisará seguir as regras, se estiver falando de um projeto de código aberto ou grande com uma equipe distribuída.

Desconhecido
fonte
2
sem uma explicação, essa resposta pode se tornar inútil se outra pessoa postar uma opinião oposta. Por exemplo, se alguém postar uma declaração como "siga as regras, se o seu projeto for sobre projetos especiais, por exemplo, um projeto de governo ou exército, mas você não precisará seguir as regras, se estiver falando de um código aberto ..." , como essa resposta ajudaria o leitor a escolher duas opiniões opostas? Considere editar ing-lo em uma melhor forma
mosquito
2
Uknown: você ficaria surpreso ao saber quantas padrões existem em projetos gov ...
Deer Hunter