C23: Um C Um Pouco Melhor
C23, a mais recente revisão do padrão da linguagem C, introduz um conjunto de recursos incrementais como inferência de tipo com `auto`, `typeof`, uma forma de palavra-chave de `static_assert`, sintaxe de inicialização mais limpa e a remoção de construções legadas como trigraphs e definições de função no estilo K&R. Os comentaristas se dividem sobre se essas mudanças melhoram de fato o C: alguns comemoram macros genéricas melhores, aritmética verificada mais segura e maior alinhamento com extensões de compilador já existentes e com C++, enquanto outros veem isso como ajustes superficiais que não resolvem problemas antigos como strings, módulos e gerenciamento de recursos mais seguro. A conversa também situa o C23 em um panorama mais amplo, no qual muitos projetos novos de sistemas favorecem C++ ou Rust, e em que linguagens alternativas (Zig, D, Nim, Ada etc.) competem para oferecer interoperabilidade com C mais segura ou mais ergonômica.
Auto, typeof e “genéricos” em C23
- O reaproveitamento de
autoé visto por alguns como uma escolha estranha; muitos esperam que seja um “não” de estilo em código C sério, ao contrário de C++. - Outros argumentam que ele é realmente útil em C:
- Evita nomes de tipos verbosos e prefixos
struct/enum. - Ajuda com macros genéricas (por exemplo,
SWAP(a,b)usandoauto tmp = a;) e com tipos inteiros de largura fixa. - Padroniza extensões
__auto_typejá existentes.
- Evita nomes de tipos verbosos e prefixos
typeoftambém é adicionado; alguns observam que agora você pode escreverconst typeof(var1) tmp = var1;.- Há debate sobre se
_Genericrealmente conta como “genéricos”: alguns o veem como sobrecarga/seleção por tipo, não como estruturas de dados paramétricas; outros dizem que ainda atende ao critério de “genérico.”
Outros ajustes de linguagem do C23
static_asserttorna-se uma palavra-chave; o C11 já tinha_Static_asserte uma macro, mas agora ele pode ser usado sem<assert.h>.func()agora é explicitamente equivalente afunc(void), e parâmetros sem nome são permitidos.- A inicialização de structs com
{}(zero-init) agora é válida (struct foo x = {};), alinhando com C++. - A remoção de trigraphs e das antigas declarações de funções no estilo K&R é bem-vinda como uma limpeza de idiossincrasias históricas.
- Alguns gostariam que o C23 tivesse um recurso
defer/RAII embutido; existe uma proposta desse tipo, mas ela ainda é “exploratória.”
Suporte de toolchain e compiladores
- Uma referência ao cppreference mostra que o GCC 13 tem suporte ao C23 relativamente amplo; o Clang está atrás em vários recursos.
- Explicações oferecidas: o design modular do LLVM e forks corporativos desaceleram a evolução do front-end; grandes contribuidores focam em backends ou em outras linguagens.
- O Pelles C supostamente suporta quase todos os recursos do C23, incluindo
#embed. - Historicamente, o MSVC negligenciava C, mas mais recentemente oferece suporte ao C17 (menos alguns recursos opcionais do C99); o momento para o C23 ainda é incerto.
C vs C++ e filosofia de linguagem
- Alguns argumentam que C++ já é “um C melhor” e que o C23 é, em grande parte, um retroporte de recursos do C++.
- Outros respondem que C e C++ hoje servem a domínios diferentes; a complexidade do C++, sua meta-programação e a geração oculta de código são vistas como inadequadas para certos usos embarcados/de baixo nível.
- As analogias variam: de “C++ é um cybertruck para a bicicleta do C” (criticada como imprecisa) até “C é ferramenta manual, C++ adiciona ferramentas elétricas.”
- Há debate sobre exceções e RAII em embarcados: alguns dizem que RAII é simples e útil; outros se preocupam com ciclos de vida de objetos menos explícitos.
Headers, módulos e superfície de API
- Alguns gostariam que o C tivesse módulos/imports de verdade em vez de headers, para evitar duplicação e acelerar builds, talvez com
importao lado do legado#include. - Outros gostam da separação entre header e implementação no C para expor claramente uma API pública; observam que isso é ortogonal a o idioma ter ou não um sistema de módulos.
- Há discussão de que módulos mais fortes poderiam quebrar parte da interoperabilidade entre C e C++, o que é politicamente sensível.
Alternativas memory-safe e FFI com C
- Um longo subthread explora “linguagens pequenas, estáveis e memory-safe com excelente FFI com C e sem grande perda de desempenho.”
- Entre as candidatas mencionadas estão Zig, D, Rust, Nim, V, Vala, LuaJIT, Ada, várias Scheme e Lisps, Swift, Julia e Go.
- Os tradeoffs destacados:
- Segurança de memória verdadeira geralmente implica GC ou borrowing no estilo Rust; ambos complicam o FFI e/ou a simplicidade.
- FFI com C fácil e de overhead zero tende a enfraquecer garantias fortes de segurança (bugs podem entrar via C).
- Vários comentaristas argumentam que a lista exata de desejos talvez seja impossível de satisfazer completamente; no máximo, dá para aproximá-la com compromissos diferentes.