Pregunta

La mayoría del código que he leído utiliza un int para el error estándar de manipulación (valores de retorno de las funciones y tal). Pero me pregunto si hay algún beneficio que se tenía del uso de un uint_8 será un compilador - léase: la mayoría de los compiladores de C en la mayoría de las arquitecturas - producir instrucciones utilizando el modo de dirección inmediata - es decir, incorporar el número entero de 1 byte en el instrucción ? La instrucción clave que estoy pensando es la comparación después de una función, utilizando uint_8 como su tipo de retorno, retornos.

Podría estar pensando en las cosas de forma incorrecta, como la introducción de un tipo de 1 byte causas justas problemas de alineación - Probablemente hay una razón perfectamente cuerdo qué compila como para empacar las cosas en 4 bytes y esto es posiblemente la razón todo el mundo sólo utiliza enteros -. y dado que esta es la pila problema relacionado más que el montón no hay ninguna sobrecarga real

Hacer lo correcto es lo que estoy pensando. Pero permite decir por ejemplo para el bien de la discusión se trata de un microprocesador barato popular para un reloj inteligente y que está configurado con 1k de memoria pero tiene diferentes modos de direccionamiento en su conjunto de instrucciones: D

Otra cuestión a especializarse un poco la discusión (86) sería: es la literal en:

uint_32 x=func(); x==1;

y

uint_8 x=func(); x==1;

del mismo tipo? o será el compilador generará un 8 bytes literal en el segundo caso. Si es así, puede utilizarlo para generar una comparación de instrucción que tiene el literal como un valor inmediato y el int devuelto como una referencia de registro. Ver tipos de instrucciones CMP. .

Otra refference para el conjunto de instrucciones x86.

¿Fue útil?

Solución

Esto es lo que un compilador particular, va a hacer por el siguiente 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>

una instrucción de 3 bytes para el CMP. si foo () devuelve un char, obtenemos  b: 3c 1f cmp $ 0x1f,% de Al

Si usted está buscando la eficiencia sin embargo. No asuma comparando cosas en% a1 es más rápido que la comparación con el% eax

Otros consejos

Puede haber muy pequeñas diferencias de velocidad entre los diferentes tipos integrales en una arquitectura particular. Pero no se puede confiar en ella, puede cambiar si se muda a un hardware diferente, e incluso puede correr más lento si se actualiza a un hardware más nuevo.

Y si se habla de x86 en el ejemplo que está dando, se hace una suposición falsa: An necesidades inmediatas como de tipo uint8_t.

En realidad immediates 8 bits incrustados en la instrucción son de tipo int8_t y se puede utilizar con bytes, palabras, dwords y QWords, en notación C: char, short, int y long long

.

Así que en esta arquitectura no habría ningún beneficio en absoluto, ni el tamaño ni el código de velocidad de ejecución.

Debe utilizar tipos int int o unsigned para sus cálculos. El uso de tipos más pequeños sólo para compuestos (structs / arrays). La razón de ello es que int se define normalmente ser del tipo integral "natural más" para el procesador, el resto de tipo derivado puede requerir procesamiento para trabajar correctamente. Tuvimos en nuestro proyecto compilado con gcc en Solaris SPARC para el caso de que acceda a 8 y variable de 16 bits añade una instrucción al código. Al cargar un tipo más pequeño de la memoria que tenía que asegurarse de que la parte superior del registro se establece correctamente (extensión de signo para el tipo firmado o 0 para firmar). Esto hizo que el código de tiempo y aumento de la presión en los registros, que se deterioraron las otras optimizaciones.

Tengo un ejemplo concreto:

he declarado dos variables de una estructura como uint8_t y tengo que código en Sparc Asm:

    if(p->BQ > p->AQ)

fue traducido en

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  !

Y aquí lo que me dieron cuando me declaré las dos variables 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  !

Dos operaciones aritméticas y menos 2 registros más para otras cosas

Procesadores normalmente le gusta trabajar con sus tamaños Registro naturales, que en C es 'int'.

Aunque hay excepciones, estás pensando demasiado en un problema que no existe.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top