O que é uint_fast32_t e por que deveria ser usado em vez do int e uint32_t regulares?

110

Portanto, a razão para typedef: tipos de dados primitivos ed é abstrair a representação de baixo nível e torná-la mais fácil de compreender (em uint64_tvez do long longtipo, que é de 8 bytes).

No entanto, existe o uint_fast32_tque tem o mesmo typedefque uint32_t. Usar a versão "rápida" tornará o programa mais rápido?

Amumu
fonte
long long pode não ter 8 bytes, é possível ter long long com 1 byte (no caso de CHAR_BIT ter pelo menos 64) ou com 3738383 bytes. também uint64_t pode ter 1,2,4 ou 8 bytes, CHAR_BIT deve ter 64, 3, 16 ou 8 para isso.
12431234123412341234123

Respostas:

134
  • intpode ser tão pequeno quanto 16 bits em algumas plataformas. Pode não ser suficiente para seu aplicativo.
  • uint32_tnão tem garantia de existência. É um opcional typedefque a implementação deve fornecer iff tem um tipo inteiro não assinado de exatamente 32 bits. Alguns têm bytes de 9 bits, por exemplo, portanto, não têm um uint32_t.
  • uint_fast32_tafirma sua intenção claramente: é um tipo de pelo menos 32 bits que é o melhor do ponto de vista do desempenho. uint_fast32_tpode ter de fato 64 bits. Depende da implementação.

... existe uint_fast32_tque tem o mesmo typedef que uint32_t...

O que você está olhando não é o padrão. É uma implementação particular (BlackBerry). Então você não pode deduzir daí que uint_fast32_té sempre o mesmo que uint32_t.

Veja também:

Yakov Galka
fonte
35
Boa resposta. Para completar, pode-se apontar a diferença uint_least32_ttambém, que é o mesmo, uint_fast32_texceto que favorece lojas menores em vez de velocidade.
Damon
2
Por que o número inteiro mais rápido com pelo menos 32 bits de largura seria maior que 32 bits? Eu sempre pensei que se houvesse menos bits, haveria menos bits que a CPU teria para trabalhar, portanto mais rápido. O que estou perdendo aqui?
Shane Hsu
12
@ShaneHsu: digamos que uma CPU de 64 bits terá um verão de 64 bits, que soma os números de 64 bits em um ciclo. Não importa se tudo o que você deseja fazer é trabalhar com números de 32 bits, não será mais rápido do que um ciclo. Agora, embora não seja assim em x86 / amd64, inteiros de 32 bits podem nem mesmo ser endereçáveis. Em tal caso, trabalhar neles requer operações adicionais para extrair os 32 bits de, digamos, unidades alinhadas de 64 bits. Veja também a questão vinculada. O padrão C ++ é escrito de forma que possa funcionar em uma máquina com palavras de 37 bits ... portanto, nenhum tipo de 32 bits.
Yakov Galka,
42

A diferença está na exatidão e disponibilidade.

O doc aqui diz:

tipo inteiro sem sinal com largura de exatamente 8, 16, 32 e 64 bits, respectivamente ( fornecido apenas se a implementação suportar diretamente o tipo ):

uint8_t
uint16_t
uint32_t
uint64_t

E

tipo inteiro não assinado não assinado mais rápido com largura de pelo menos 8, 16, 32 e 64 bits, respectivamente

uint_fast8_t
uint_fast16_t
uint_fast32_t
uint_fast64_t    

Portanto, a diferença é bastante clara: uint32_té um tipo que tem exatamente 32 bits, e uma implementação deve fornecê-lo apenas se tiver exatamente 32 bits, e então pode definir esse tipo como uint32_t. Isso significa que uint32_tpode ou não estar disponível .

Por outro lado, uint_fast32_té um tipo que possui pelo menos 32 bits, o que também significa, se uma implementação pode ser digitada uint32_tcomo uint_fast32_t se ela fornecesse uint32_t. Se não fornecer uint32_t, uint_fast32_tpode ser um typedef de qualquer tipo que tenha pelo menos 32bits.

Nawaz
fonte
3
Mas qual é a razão que torna, por exemplo, uint_fast32_t mais rápido do que uint32_t? Por que é mais rápido?
Destruidor
2
@PravasiMeet: Nem todos os inteiros são acessados ​​da mesma maneira. Alguns são mais fáceis de acessar do que outros. Mais fácil significa menos computação, mais direto, o que resulta em acesso mais rápido. Agora uint32_té exatamente 32 bits em todos os sistemas (se existir), o que pode não ser mais rápido em comparação com aquele que tem, digamos, 64 bits. uint_fast32_tpor outro lado, pelo menos 32 bits, pode ser até 64 bits.
Nawaz
10
@Destructor: em alguns processadores, se uma variável for armazenada em um registrador mais longo, o compilador pode ter que adicionar código extra para cortar quaisquer bits extras. Por exemplo, se uint16_t x;for armazenado em um registro de 32 bits no ARM7-TDMI, o código x++;pode precisar ser avaliado como x=((x+1)<<16)>>16);. Em compiladores para essa plataforma, uint_fast16_tprovavelmente seria definido como sinônimo uint32_tde evitar isso.
supercat
por que [u]int_(fast|least)N_ttambém não são opcionais? Certamente nem todas as arquiteturas são exigidas pelo Padrão para suportar tipos primitivos de pelo menos 64 bits. No entanto, a formulação para stdint.himplica que eles devem. Parece estranho para mim que tenhamos reforçado isso desde 1999, alguns anos antes da computação de 64 bits se tornar dominante - para não falar do atraso (em muitos casos ainda atual) das arquiteturas embarcadas. Isso parece um grande descuido para mim.
underscore_d
1
@underscore_d: Não há nenhuma razão particular, por exemplo, que o Padrão não possa ser aplicável a uma implementação PIC12 com 16 bytes de RAM de dados e espaço para 256 instruções. Tal implementação precisaria rejeitar muitos programas, mas isso não deveria impedi-la de se comportar de maneira definida para programas cujas necessidades ela pudesse satisfazer.
supercat
4

Quando você está #include inttypes.hem seu programa, obtém acesso a várias maneiras diferentes de representar números inteiros.

O tipo uint_fast * _t simplesmente define o tipo mais rápido para representar um determinado número de bits.

Pense assim: você define uma variável do tipo shorte a usa várias vezes no programa, o que é totalmente válido. No entanto, o sistema no qual você está trabalhando pode funcionar mais rapidamente com valores do tipo int. Ao definir uma variável como tipo uint_fast*t, o computador simplesmente escolhe a representação mais eficiente com a qual pode trabalhar.

Se não houver diferença entre essas representações, o sistema escolhe a que deseja e a usa de forma consistente em todas as partes.

Harley Sugarman
fonte
9
Por que inttypes.h e não stdint.h? Parece que inttypes.h contém apenas vários fluff ligeiramente úteis, além de incluir stdint.h?
Lundin
@underscore_d Eu sei a diferença. Mas quem usa stdio.h em programas profissionais, independentemente da área de aplicação?
Lundin
@Lundin Eu não tenho ideia de quem eles são, ou se existem! Achei que poderia ser útil fornecer um link detalhando o que é esse "buço levemente útil" ;-) Talvez ajude as pessoas a perceberem que você está certo e que não precisam dele.
sublinhado_d
-1

Observe que a versão rápida pode ser maior que 32 bits. Enquanto o int rápido vai caber bem em um registro e ser alinhado e coisas do tipo: mas, ele vai usar mais memória. Se você tiver grandes matrizes desses, seu programa será mais lento devido a mais acessos de cache de memória e largura de banda.

Não creio que o CPUS moderno se beneficie do fast_int32, já que geralmente a extensão do sinal de 32 a 64 bits pode acontecer durante a instrução de carregamento e a ideia de que existe um formato inteiro 'nativo' que é mais rápido é antiquada.

Gil Colgate
fonte