de programação C e eficiência variável error_code
-
11-09-2019 - |
Pergunta
usos A maioria dos códigos que eu já li um int
para tratamento de erros padrão (valores de retorno de funções e tal). Mas eu estou querendo saber se existe algum benefício a ser tido de usar um uint_8
será um compilador - leia-se: a maioria dos compiladores C na maioria das arquiteturas - instruções de produzir usando o modo de endereço imediata - ou seja, inserir o número inteiro de 1 byte para o instrução? A instrução chave que eu estou pensando é a comparar depois de uma função, utilizando uint_8 como seu tipo de retorno, retorna.
Eu poderia estar pensando sobre as coisas de forma incorreta, como a introdução de um tipo 1 byte apenas provoca problemas de alinhamento - provavelmente há uma razão perfeitamente sã porque compila gostaria de embalar as coisas em 4 bytes e este é possivelmente o motivo todo mundo usa ints -. e desde que esta é uma questão pilha relacionada ao invés da pilha não há nenhuma sobrecarga verdadeiro
Fazer a coisa certa é o que eu estou pensando. Mas vamos dizer que dizer para o bem do argumento este é um microprocessador barato popular para um relógio inteligente e que está configurado com 1k de memória, mas tem diferentes modos de endereçamento em seu conjunto de instruções: D
Outra questão a se especializar um pouco a discussão (x86) seria: é a literal em:
uint_32 x=func(); x==1;
e
uint_8 x=func(); x==1;
o mesmo tipo? ou será o compilador gera um literal de 8 bytes no segundo caso. Se assim for, pode usá-lo para gerar uma instrução de comparar qual tem o literal como um valor imediato eo int retornado como uma referência de registo. Veja CMP tipos de instruções. .
Solução
Aqui está o que um compilador particular irá fazer para o seguinte código:
extern int foo(void) ;
void bar(void)
{
if(foo() == 31) { //error code 31
do_something();
} else {
do_somehing_else();
}
}
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 08 sub $0x8,%esp
6: e8 fc ff ff ff call 7 <bar+0x7>
b: 83 f8 1f cmp $0x1f,%eax
e: 74 08 je 18 <bar+0x18>
10: c9 leave
11: e9 fc ff ff ff jmp 12 <bar+0x12>
16: 89 f6 mov %esi,%esi
18: c9 leave
19: e9 fc ff ff ff jmp 1a <bar+0x1a>
a instrução 3 bytes para o CMP. se foo () retorna um char, obtemos b: 3c 1F cmp $ 0x1f,% al
Se você está procurando a eficiência embora. Não assuma comparando coisas em% a1 é mais rápido do que comparando com% eax
Outras dicas
Pode haver pequenas diferenças de velocidade entre os diferentes tipos integrais sobre uma arquitetura particular. Mas você não pode contar com ele, isso pode mudar se você se mover para um hardware diferente, e pode até ficar mais lento se você atualizar para hardware mais recente.
E se você falar sobre x86 no exemplo você está dando, você faz uma falsa premissa: Um necessidades imediatas para ser do tipo uint8_t
.
Na verdade imediatos 8 bits incorporados na instrução são do tipo int8_t
e pode ser usado com bytes, palavras, e dwords qwords, em notação C:. char
, short
, int
e long long
Assim, nesta arquitetura não haveria nenhum benefício em tudo, nem o tamanho do código, nem a velocidade de execução.
Você deve usar tipos int int ou não assinados para seus cálculos. Utilizando tipos menores apenas para compostos (structs / matrizes). A razão para isso é que int é normalmente definido como sendo o tipo integral "natural mais" para o processador, todo outro tipo de derivado pode necessitar de processamento a funcionar correctamente. Tivemos no nosso projeto compilado com gcc no Solaris para SPARC o caso que acessa a 8 e 16 bit variável acrescentou uma instrução para o código. Ao carregar um tipo menor de memória que ele tinha que ter certeza da parte superior do registo foi correctamente definido (extensão de sinal para o tipo assinado ou 0 para não assinado). Este feito o código de mais tempo e o aumento da pressão nos registos, o que deterioraram as outras optimizações.
Eu tenho um exemplo concreto:
Eu declarei duas variáveis ??de uma struct como uint8_t e tenho esse código em Sparc Asm:
if(p->BQ > p->AQ)
foi traduzido em
ldub [%l1+165], %o5 ! <variable>.BQ,
ldub [%l1+166], %g5 ! <variable>.AQ,
and %o5, 0xff, %g4 ! <variable>.BQ, <variable>.BQ
and %g5, 0xff, %l0 ! <variable>.AQ, <variable>.AQ
cmp %g4, %l0 ! <variable>.BQ, <variable>.AQ
bleu,a,pt %icc, .LL586 !
E aqui o que eu tenho quando eu declarou que as duas variáveis ??como uint_t
lduw [%l1+168], %g1 ! <variable>.BQ,
lduw [%l1+172], %g4 ! <variable>.AQ,
cmp %g1, %g4 ! <variable>.BQ, <variable>.AQ
bleu,a,pt %icc, .LL587 !
Duas operações aritméticas menos e 2 registros mais para outras coisas
Processadores normalmente gosta de trabalhar com seus tamanhos registo naturais, que em C é 'int'.
Embora haja exceções, você está pensando muito em um problema que não existe.