A única razão pela qual eu usaria o long
hoje é ao chamar ou implementar uma interface externa que o utiliza.
Como você diz em sua postagem, curta e int tem características razoavelmente estáveis em todas as principais plataformas de desktop / servidor / dispositivos móveis hoje e não vejo nenhuma razão para isso mudar no futuro previsível. Então, vejo poucos motivos para evitá-los em geral.
long
, por outro lado, é uma bagunça. Em todos os sistemas de 32 bits, estou ciente de que tinha as seguintes características.
- Tinha exatamente 32 bits de tamanho.
- Era do mesmo tamanho que um endereço de memória.
- Era do mesmo tamanho que a maior unidade de dados que poderia ser mantida em um registro normal e trabalhada com uma única instrução.
Grandes quantidades de código foram escritas com base em uma ou mais dessas características. No entanto, com a mudança para 64 bits, não foi possível preservar todos eles. Plataformas Unix-like foram para LP64 que preservaram as características 2 e 3 ao custo da característica 1. Win64 foi para LLP64 que preservou a característica 1 ao custo das características 2 e 3. O resultado é que você não pode mais confiar em nenhuma dessas características e que a IMO deixa poucas razões para usar long
.
Se você quiser um tipo que tenha exatamente 32 bits de tamanho, use int32_t
.
Se você quiser um tipo que tenha o mesmo tamanho de um ponteiro, use intptr_t
(ou melhor uintptr_t
).
Se você quer um tipo que é o maior item que pode ser trabalhado em um único registrador / instrução, infelizmente eu não acho que o padrão forneça um. size_t
deve estar certo na maioria das plataformas comuns, mas não estaria em x32 .
P.S.
Eu não me incomodaria com os tipos "fast" ou "least". Os tipos "mínimos" só importam se você se preocupa com a portabilidade para realmente obscurecer as arquiteturas em que CHAR_BIT != 8
. O tamanho dos tipos "rápidos" na prática parece ser bastante arbitrário. O Linux parece torná-los pelo menos do mesmo tamanho que o ponteiro, o que é ridículo em plataformas de 64 bits com suporte rápido a 32 bits, como x86-64 e arm64. O IIRC iOS torna-os o menor possível. Não tenho certeza do que outros sistemas fazem.
P.P.S
Um motivo para usar o unsigned long
(mas não o% normallong
) é porque ele tem o comportamento do módulo. Infelizmente, devido às regras de promoção erradas de C, tipos não assinados menores que int
não possuem comportamento de módulo.
Em todas as principais plataformas atuais, uint32_t
é do mesmo tamanho ou maior que int e, portanto, possui comportamento de módulo. No entanto, houve historicamente e teoricamente poderia haver nas plataformas futuras onde int
é de 64 bits e, portanto, uint32_t
não tem comportamento de módulo.
Pessoalmente, eu diria que é melhor entrar no habbit de forçar o comportamento do módulo usando "1u *" ou "0u +" no início de suas equações, pois isso funcionará para qualquer tamanho de tipo não assinado.