Modern C Edição C23
(gustedt.wordpress.com)- A edição revisada de Modern C foi disponibilizada para download gratuito, permitindo revisar materiais de estudo e referência da linguagem C com base no C23
- O foco central da revisão é incorporar o C23, ajudando na transição para o novo padrão em sintonia com o cronograma e o momento do processo de publicação da ISO
- Novos lançamentos dos principais compiladores já implementam a maior parte dos recursos do C23, conectando as mudanças do livro não apenas a uma apresentação experimental, mas também a ambientes reais de uso
- Mudanças de linguagem e biblioteca como
_BitInt(N),nullptr,auto,typeofeconstexprforam amplamente refletidas, impactando também a forma de escrever código C existente - Para permitir testar isso imediatamente em plataformas existentes, foram adicionados um apêndice de transição e headers
includetemporários, mas o MEAP da Manning ainda está em andamento
Material gratuito e documentos do padrão
- A edição C23 de Modern C pode ser baixada gratuitamente
- Download: https://hal.inria.fr/hal-02383654
- Na página dedicada do livro, também é possível encontrar materiais relacionados
- Página oficial: https://gustedt.gitlabpages.inria.fr/modern-c/
- O link para baixar os exemplos de código fornecidos com o livro também está nessa página
- A edição revisada ajusta várias explicações, mas seu objetivo principal é refletir o novo padrão C, o C23
- Entre os documentos com acesso público, o material mais próximo do conteúdo do novo padrão é o PDF N3220
- Novos lançamentos dos principais compiladores já implementam a maior parte dos novos recursos trazidos pelo C23
Mudanças da linguagem C23 e suporte à transição
- As mudanças relacionadas a inteiros ocupam uma parte importante
- Adição do novo tipo de precisão em bits
_BitInt(N) - Inclusão de novos headers da biblioteca C para aritmética com verificação de overflow e manipulação de bits
- Reflexo da possibilidade de tipos de 128 bits em arquiteturas modernas
- Inclui melhorias práticas no tipo enum
- Adição do novo tipo de precisão em bits
- Outros novos conceitos do C23 também estão incluídos
- A constante
nullptre o tipo associado a ela - Anotações sintáticas por meio de attributes
- Ferramentas de programação genérica de tipos, incluindo
autoetypeof - Inicialização padrão com
{}aplicada também a arrays de comprimento variável constexprpara constantes nomeadas de todos os tipos
- A constante
- O novo material também aborda expressões compostas, lambdas, “internacionalização” e até uma abordagem abrangente para falhas de programa
- Foram adicionados um apêndice e headers
includetemporários para começar a usar C23 imediatamente em plataformas existentes - O MEAP da nova edição da Manning ainda está aberto
- MEAP: https://www.manning.com/books/modern-c-third-edition
- A data final de publicação da edição C23 da versão da Manning ainda não é conhecida
1 comentários
Opiniões no Hacker News
Ao contrário da ordem de armazenamento da minha máquina, little-endian, o formato em que a representação dos dígitos mais significativos vem primeiro é chamado de big-endian; dizer que ambos são comumente usados em processadores modernos parece um pouco exagerado, já que, fora o s390x, quase não sobrou nada
Imagino que em breve apareçam comentários sobre as arquiteturas big-endian de nicho/obsoletas favoritas de todo mundo
Como em outro comentário mais votado, “moderno” não quer dizer necessariamente popular ou amplamente usado
AIX e IBM i talvez não sejam tão ativos quanto os mainframes da IBM, mas dá para dizer que o AIX está mais vivo até que Solaris ou HP/UX, ainda mais quando comparado aos muitos Unix comerciais de antigamente. O IBM i também está sobrevivendo por pouco, mas está muito mais vivo do que plataformas midrange legadas concorrentes cujo suporte oficial do fornecedor foi encerrado, como o HP MPE
O aspecto mais importante de C é a portabilidade. O ponto central é ir de pequenos microcontroladores a quase todas as plataformas de computação, mas tenho dúvidas de que uma nova versão de C seja adotada nesse nível
Se eu quisesse usar algo de ponta, acho que escolheria C++2x ou Rust em vez de C. Estou deixando passar algo? Fico curioso sobre quais são as vantagens desse tal C moderno
Se a ideia é estar na ponta, recomendo Zig. A complexidade da linguagem é muito menor que a de C++ moderno e Rust. Um bom efeito colateral menos chamativo do C23 é aproximar sintaxes como
... = {}e{0}das de C++, tornando menos incômodo para mantenedores de bibliotecas C dar suporte a pessoas que querem compilar código C com um compilador C++0bé amplamente usada no mundo dos microcontroladoresToolchains de microcontroladores em geral são construídas em cima do GCC, então recebem recursos de graça. Ainda existem compiladores C proprietários que estão sempre atrasados, mas eles não são tão importantes quanto eram há 20 anos
Se você não mira embarcados ou um conjunto muito amplo de arquiteturas, também não há motivo para não usar C23 a partir de hoje
thread_localjá é usado em algumas plataformas de microcontroladores, mas antes do C11 era completamente ilegal. Ainda assim, ele simplifica muito a gestão de memória em ambientes com threadsHá algum motivo para entrar no mundo C++ só por causa disso?
Pessoalmente, coisas como
guard,defer,auto,constexprenullptrtornam C muito mais complexo. Eu escolho C porque preciso de simplicidade; se eu quisesse complexidade, normalmente escolheria C++, mesmo sem querer muito, ou então Go — ou Elixir, se fosse para servidor_BitInt(N)também é feio e me lembra_Bool, que felizmente agora viroubool.constexprenullptrtêm cheiro forte demais de C++. Ainda assim, Modern C é um ótimo livro, e eu o tenho usado bem para C99, que pretendo continuar usandoNULL?” é respondida lendo os documentos relacionados, graças a uma das poucas vantagens da padronização ISO: https://wg21.link/p2312Em resumo, passar um argumento
NULLpara macros genéricas por tipo pode gerar resultados surpreendentes, e o status de expressões condicionais como(1 ? 0 : NULL)e(1 ? 1 : NULL)muda dependendo de comoNULLé definido. Além disso, passarNULLpara uma função variádica que espera um ponteiro pode ter consequências sérias. Em muitas arquiteturas atuais,intevoid*têm tamanhos diferentes; seNULLfor simplesmente0, um argumento do tamanho errado será passado à funçãoÉ parecido com construir uma casa. Um martelo e uma chave de fenda são muito simples, e um guindaste é extremamente complexo, mas quem simplifica a construção da casa é o guindaste. Se você tivesse que construir uma casa só com martelo e chave de fenda, precisaria inventar um procedimento extremamente complexo
Com linguagens de programação é a mesma coisa. Criar contêineres genéricos em C++ é trivial, mas em C é muito difícil. Dá para imitar até certo ponto com
void *e casts manuais, mas é trabalhoso, propenso a erros e torna o código mais complexoO mesmo vale para
std::sorteqsort. Com o poder de templates e objetos de função, a implementação fica mais simples e rápida. Não é preciso passarvoid *nem desreferenciar em tempo de execução, e a comparação pode ser colocada na própria definição da função. Não há chamada indireta, não há passagem pela pilha, e a função de comparação ainda pode ser inlinada. Complexidade da linguagem não significa complexidade de implementaçãoautoé útil principalmente quando se mexe com macros genéricas por tipo, mas é melhor não usá-lo em código comum. Espero que evitem aquela loucura de almost always auto que virou moda por um tempo no mundo C++Infelizmente, há pequenas diferenças entre compiladores. Pelo que lembro, Clang implementava o
autono estilo C++ e GCC implementava oautono estilo C, então havia diferenças sutis com ponteirosauto. Não sei se essa diferença já foi corrigida_BitInt(N)normalmente não é usado diretamente; usa-se umtypedefcom a largura necessária. Por exemplo,typedef _BitInt(2) u2;. Sintaxes feias como_Bsão necessárias porque combinações de sublinhado seguido de letra maiúscula são reservadas pelo padrão C, para evitar conflito com código existente ao adicionar pequenos recursos à linguagem. O nome_Boolexiste pelo mesmo motivo. Pelo que sei,deferna verdade não entrou no C23A definição antiga nem sequer especificava se
NULLera um ponteiro ou um inteiro. Por isso, em plataformas que não seguiam a exigência do POSIX de((void*)0), era uma armadilha sob os pés, sem ser nem tipo de ponteiro nem tamanho de ponteiroconstexprenullptrtêm cheiro de C++ provavelmente porque foram reimportados do C++. Ainda assim,NULLcontinua podendo ser usado; por fora, parece ter sido redefinido comonullptrexeclp("echo", "echo", "Hello, world!", NULL);Este código não tem esse bug:
execlp("echo", "echo", "Hello, world!", nullptr);Isto também está ok:
execlp("echo", "echo", "Hello, world!", (char *)NULL);Eu ia perguntar se havia uma boa lista de livros de C, mas encontrei a resposta por conta própria. Aqui, Modern C é classificado como intermediário
https://stackoverflow.com/questions/562303/the-definitive-c-...
Como companheiros modernos para o C de K&R, considero 21st Century C, de Ben Klemens, e C Programming: A Modern Approach, de King, alternativas mais acessíveis
Pessoalmente, prefiro Effective C a Modern C. Modern C é tão rigoroso que parece ler uma especificação comentada da linguagem, algo que pode ser necessário para especialistas; para alguém como eu, que usa C de forma mais leve, é uma leitura entediante
Gosto bastante de algumas das extensões High C da Metaware
https://news.ycombinator.com/item?id=41647843
https://news.ycombinator.com/item?id=38938402
Há mais de um ano venho usando C++ moderno em um projeto pessoal, um interpretador de linguagem, mas por causa da carga mental do C++ e dos problemas de ferramental continuo pensando em migrar para C. O IntelliSense do Visual Studio ainda quase não funciona quando se usam módulos do C++20, e, por causa das falhas da linguagem, coisa demais acaba sendo empurrada para as interfaces, deixando os tempos de compilação horrorosos
Por outro lado, já me acostumei tanto com classes, funções-membro, programação genérica e namespaces que talvez eu já tenha caído na armadilha
Para esse caso, você já considerou C#? O Visual Studio combina muito melhor com C#
No Preview do macOS, clicar nos links do sumário na barra lateral não funciona direito
Só faz alguns anos que, em uma biblioteca que mantenho, pude confiar que todos os compiladores C davam suporte a C99: https://github.com/eyalroz/printf
Mas, alguns anos depois, como sempre, foi aberta uma issue pedindo compatibilidade com C89 por causa de alguma toolchain embarcada antiquíssima. Então C23 é legal, mas a sensação é de: vamos conversar de novo daqui a uns 20 anos
Alguém pode linkar um texto que explique, na prática, por que C está de fato parado no C99? Quase não vejo projetos dignos de menção usando recursos posteriores ao C11
Como C ficou praticamente congelado por décadas, a base de usuários parece ter se autosselecionado para pessoas que gostam de C como ele é e não se importam em dar suporte a compiladores velhos e cheios de tralhas. Quem perdeu a paciência ou queria uma linguagem do século XXI foi para C++/Rust/Zig etc.
Por volta de 2010, o MSVC ainda era muito importante, o que soa estranho do ponto de vista atual, em que parece que a maioria dos desenvolvedores migrou para Linux. Por outro lado, também não há muitos projetos que realmente precisem de recursos do C11. O C11 também tirou de C99 os VLAs, o que não foi uma perda tão lamentável. C23 talvez seja a primeira versão desde C99 para a qual muitas codebases em C possam realmente valer a pena fazer upgrade