Pergunta

Eu já trabalhei em um número de diferentes sistemas embarcados.Todos eles têm usado typedefs (ou #defines) para tipos como UINT32.

Esta é uma boa técnica, pois as unidades de casa, o tamanho do tipo para o programador e o torna mais consciente das possibilidades para que estouro, etc.

Mas, em alguns sistemas, você sabe que o compilador e o processador não vai mudar durante a vida do projeto.

Então, o que deve influenciar a sua decisão de criar e impor projecto-tipos específicos?

EDITAR Eu acho que eu consegui perder a essência da minha pergunta, e talvez ele realmente dois.

Com o embedded programação, você pode precisar de tipos de tamanho específico para interfaces e também para lidar com recursos limitados, tais como RAM.Isso não pode ser evitado, mas você pode optar por usar os tipos básicos de compilador.

Para tudo o resto, os tipos têm menos importância.
Você precisa ser cuidadoso para não causar sobrecarga e pode precisa prestar atenção para fora para registro e uso de pilha.O que pode levar você para UINT16, UCHAR.O uso de tipos, tais como UCHAR pode adicionar compilador 'cotão' no entanto.Porque os registos são normalmente maiores, alguns compiladores podem adicionar código para forçar o resultado para o tipo.

i++;
pode tornar-se
ADD REG,1
AND REG, 0xFF
o que é desnecessário.

Então eu acho que a minha pergunta deveria ter sido :-

dadas as limitações do software embarcado que é a melhor política a ser definido para um projeto que vai ter muitas pessoas a trabalhar - e não de todos, de quem vai ser do mesmo nível de experiência.

Foi útil?

Solução

Eu uso tipo de abstração muito raramente.Aqui estão os meus argumentos, ordenados em ordem crescente de subjetividade:

  1. Variáveis locais são diferentes dos membros do struct e matrizes no sentido de que você quer que eles se encaixam em um registrador.Em um 32b/64b destino, um local int16_t pode tornar o código mais lento comparado a um local int desde que o compilador vai ter que adicionar operações /força/ estouro de acordo com a semântica de int16_t.Enquanto C99 define um intfast_t typedef, AFAIK um simples int vai caber em um registro tão bem, e com certeza é um nome mais curto.

  2. Organizações que, como estes typedefs, quase que invariavelmente acabam com vários deles (INT32, int32_t, INT32_T, ad infinitum).As organizações que usam tipos internos são, portanto, melhor, de uma forma, tendo apenas um conjunto de nomes.Eu desejo que as pessoas usavam os typedefs stdint.h ou windows.h ou qualquer coisa existente;e quando o alvo não tem de que .h ficheiro, quão difícil é [para adicionar um?

  3. O typedefs pode, teoricamente, portabilidade auxílio, mas eu, por exemplo, nunca ganhou uma coisa deles.Há um útil sistema de porta a partir de uma 32b-alvo para um 16b um?Há um 16b sistema que não é trivial a porta para um 32b-alvo?Além disso, se a maioria dos vars são ints, você vai realmente ganhar alguma coisa com a versão de 32 bits do novo destino, mas, se eles são int16_t, você não vai.E os lugares que são difíceis para a porta tendem a necessitar de inspeção manual, de qualquer forma;antes de tentar uma porta, você não sabe onde eles estão.Agora, se alguém acha que é tão fácil para a porta de coisas, se você tem typedefs todo o lugar - chega um momento em que a porta, o que acontece para alguns sistemas, escrever um script de conversão de todos os nomes da base de código.Isso deve funcionar de acordo com o "manual de inspeção necessária" a lógica, e ele adia o esforço para o ponto no tempo onde ele realmente dá benefício.

  4. Agora, se a portabilidade pode ser um benefício teórico de typedefs, a legibilidade com certeza vai pelo ralo.Basta olhar para stdint.h: {int,uint}{max,fast,least}{8,16,32,64}_t.Muitos tipos.Um programa tem várias variáveis;é realmente muito fácil de entender o que precisa ser int_fast16_t e que precisa ser uint_least32_t?Quantas vezes estamos silenciosamente a conversão entre eles, tornando-os totalmente inútil?(Eu particularmente gosto BOOL/Bool/eBool/boolean/bool/int conversões.Todo programa escrito por um ordenado de organização, determinando typedefs está repleta de que).

  5. É claro que em C++ podemos tornar o tipo de sistema mais rigoroso, envolvendo números no modelo de instâncias de classes com operadores sobrecarregados e outras coisas.Isso significa que agora você vai receber mensagens de erro do formulário "classe Número<int,Least,32> não tem nenhum operador+ sobrecarga para o argumento de tipo de classe de Número de<unsigned long="" long,Fast,64="">os candidatos..." eu não chamo isso de "legibilidade", qualquer um.Suas chances de implementação destas classes de wrapper corretamente são microscópicas, e a maior parte do tempo você vai esperar pelas inúmeras instanciações de modelo para compilar.

Outras dicas

O padrão C99 tem um número de tamanho padrão-tipos inteiros.Se você pode usar um compilador que suporta a C99 (gcc faz), você vai encontrar estas no <stdint.h> e você só pode usá-los em seus projetos.

Além disso, ele pode ser especialmente importante no embedded projetos para tipos de uso como uma espécie de "rede de segurança" para coisas como conversões de unidades.Se você pode usar C++, eu entendo que há alguns "unidade" bibliotecas que permitem a você trabalhar em unidades físicas que são definidas pelo tipo de C++ (sistema através de modelos) que são compilados como operações subjacentes, tipos escalares.Por exemplo, essas bibliotecas não permitem que você adicione um distance_t para um mass_t porque as unidades não se alinham;você vai obter um erro do compilador.

Mesmo se você não pode trabalhar em C++ ou outro idioma que permite que você escreva código de forma, pelo menos você pode usar o C tipo de sistema para ajudar a detectar erros como que com os olhos.(Que na verdade era a intenção original de Simonyi da notação húngara.) Só porque o compilador não vai gritar com você para a adição de um meter_t para um gram_t não significa que você não deve usar tipos assim.As revisões de código será muito mais produtivo, a descoberta de erros de unidade de então.

Minha opinião é que se você está dependendo de um mínimo/máximo/tamanho específico não apenas suponha que (digamos) um unsigned int é de 32 bytes de uso uint32_t em vez disso, (assumindo que o seu compilador suporta C99).

Eu gosto de usar stdint.h tipos para a definição de APIs do sistema, especificamente, porque eles explicitamente dizer como itens grandes são.De volta aos velhos tempos do Palm OS, o sistema de APIs foram definidos usando um monte de wishy-washy de tipos como "Palavra" e a "Espada" que foram herdadas da grande clássico do Mac OS.Eles fizeram uma limpeza em vez de dizer Int16 e isso fez com que a API mais fácil para os iniciantes a entender, especialmente com o estranho, 16-bit ponteiro de problemas no sistema.Quando eles estavam projetando o Palm OS Cobalt, eles mudaram os nomes de novo para combinar com stdint.h nomes, o que torna ainda mais clara e reduzindo a quantidade de typedefs eles tinham para gerir.

Eu acredito que MISRA padrões de sugerir (precisa?) o uso de typedefs.

A partir de uma perspectiva pessoal, usando typedefs não deixa nenhuma confusão quanto ao tamanho (em bits / bytes) de determinados tipos.Eu tenho visto os desenvolvedores tentativa de ambas as formas de desenvolvimento usando o padrão de tipos e.g.int e usando tipos personalizados e.g.UINT32.

Se o código não estiver portátil há pouco real benefício no uso de typedefs, no entanto , se gosta de mim então você trabalha em ambos os tipos de software (portáteis e fixas ambiente), então ele pode ser útil para manter um padrão e usar o cutomised tipos.Pelo menos, como você diz, o programador é então muito ciente da quantidade de memória que está a utilizar.Outro fator a considerar é como 'certeza' de que o código não vai ser portado para outro ambiente?Eu vi específicos do processador código tem que ser traduzido como um hardware engieer, de repente, tive que mudar de uma placa, esta não é uma boa situação, mas devido ao costume typedefs poderia ter sido muito pior!

A coerência, a conveniência e a legibilidade."UINT32" é muito mais legível e gravável que "unsigned long long", que é o equivalente para alguns sistemas.

Além disso, o compilador e o processador que pode ser fixada para a vida de um projeto, mas o código do projeto pode ter uma nova vida em outro projeto.Neste caso, tendo consistente tipos de dados é muito conveniente.

Se o seu sistemas embarcados é de alguma forma um sistema de segurança crítico (ou similar), é fortemente aconselhado (se não necessária) para utilizar typedefs mais simples tipos.

Como TK. já disse antes, MISRA-C tem um (consultivo) a regra para fazer isso:

Regra 6.3 (consultivo): typedefs que indicam o tamanho e o sinal deve ser usado no lugar do basic tipos numéricos.

(a partir de MISRA-C de 2004;é Regra #13 (adv) de MISRA-C de 1998)


O mesmo também se aplica para C++ nesta área;por exemplo. JSF C++ padrões de codificação:

AV Regra 209 Um UniversalTypes arquivo será criado para definir toda sta ndard tipos de programadores para se usar.Os tipos incluem:[uint16, int16, uint32_t etc.]

Usando <stdint.h> torna seu código mais portável, para testes de unidade em um pc.

Ele pode mordê-lo muito difícil quando você tem testes para tudo, mas, ainda assim, quebra do seu sistema de destino devido a uma int de repente é de apenas 16 bits de comprimento.

Talvez eu seja estranha, mas eu uso o ub, ui, ul, sb, si, e sl para o meu tipos inteiros.Talvez o "eu" para 16 bits parece um pouco datado, mas eu gosto de olhar ui/si melhor do que uw/sw.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top