Como usar os tipos padrão C99 para máxima portabilidade E eficiência na maioria das plataformas?

Primeiro, aqui está o que eu entendo e penso o que é verdade para a questão.

Use tipos de dados rápidos para variáveis ​​únicas, como contadores oufor índices de loop. Por exemplo:

#define LOOP_COUNT (100U)

uint_fast8_t index;
for(index = 0; index < LOOP_COUNT; index++){
    /* Do something */
}

Eu suponho que o tipo mais adequado aqui éuint_fast8_t Desde aindex nunca pode exceder 255 e esta será a implementação mais rápida para todas as plataformas. Se eu usasseunsigned int em vez disso, será mais rápido em plataformas> = 16 bits, mas será mais lento em plataformas de <16 bitsint é de no mínimo 16 bits por padrão. Além disso, se eu usasseuint8_t será mais lento em plataformas de 8 bits, pois o compilador adicionaAND 0xFF instruções para verificar o estouro de cada incremento (meu compilador ARM7 faz isso mesmo na otimização de velocidade total).size_t também não é uma opção, pois pode ser maior que o tamanho inteiro nativo.

Lado ruim (?) Disso, se um estouro é esperado para 8 bits, isso não vai acontecer. Programador deve verificar se há overflow manualmente (como ele / ela deve IMHO), o que pode resultar em código buggy se esquecido. Além disso, o compilador (e até mesmo o PC-Lint para minha surpresa) não dará nenhum aviso / problema se LOOP_COUNT "acidentalmente" for configurado para um valor maior que 255 em plataformas> 8 bits, mas o aviso será gerado em uma plataforma de 8 bits, que reduzirá a portabilidade e introduzirá bugs, mas isso pode ser evitado com#if Verificações.

Use menos tipos de dados, tanto quanto possível, se o uso de memória é motivo de preocupação, como em matrizes ou estruturas. Por exemplo:

uint_least8_t array[100];

É a maneira mais portátil e eficiente de declarar matrizes se o uso da memória for uma preocupação. Esse tipo fornecerá uma matriz de bytes se o acesso a bytes for possível na plataforma e fornecerá a menor matriz inteira de largura acessível, caso contrário. Além disso, menos tipos podem ser usados ​​em estruturas se tivermos arrays da estrutura.

O tipo mínimo também pode sofrer os problemas que os tipos rápidos fazem, já que a largura das variáveis ​​pode ser alterada em diferentes plataformas para ambos os casos.

Evite o máximo possível de tipos de dados com largura fixa, pois eles podem nem existir em algumas plataformas, exceto acesso a registradores de hardware, mapeamento de protocolos de comunicação, etc., onde precisamos saber os bits exatos da variável. Por exemplo:

typedef struct {
    uint8_t  flags;
    uint8_t  length;
    uint8_t  data[100];
    uint16_t crc;
} __attribute__((packed)) package_t;

Usualmente__attribute__((packed)) (ou algo semelhante) deve ser usado para garantir que nenhum preenchimento seja inserido para esses casos, pois isso pode ser um problema por si só.

Agora, se a minha compreensão for verdadeira, acho que menos tipos de dados são mais propensos a serem usados ​​em matrizes ou estruturas, os tipos de dados rápidos são mais propensos a serem usados ​​para variáveis ​​individuais e tipos de dados fixos são improváveis ​​de serem usados ​​para atingir o máximo portabilidade e eficiência. Mas digitar "rápido" e "mínimo" toda vez não é animador. Então, penso em um tipo definido da seguinte forma:

    typedef [u]intN_t       os_[u|s]exactN_t;
    typedef [u]int_fastN_t  os_[u|s]N_t;
    /* I couldn't come up with a better name */
    typedef [u]int_leastN_t os_[u|s]minN_t;
    /* These may change */
    typedef uint_least8_t   os_byte_t;
    typedef uint_least16_t  os_word_t;
    /* ... */
Primeiro e a questão importante é, meu entendimento é verdadeiro?Qual seria a maneira mais portátil e eficiente de usar os tipos padrão C99 e como você os declararia se isso não fosse verdade?O meu conjunto de tipos faz sentido ou é provável que ele produza código com bugs?

Além disso, eu ficaria feliz em saber como e onde você usa os tipos padrão C99.

questionAnswers(1)

yourAnswerToTheQuestion