Usando avr-gcc como ejemplo, los tipos int se especifican para tener 16 bits de ancho. La realización de operaciones en operandos de 8 bits en C da como resultado que esos operandos se conviertan en tipos int de 16 bits debido a la promoción de enteros en C. ¿Esto significa que todas las operaciones aritméticas de 8 bits en un AVR tomarán mucho más tiempo si se escriben en C que si está escrito en asamblea debido a la promoción de enteros de C?
microcontroller
avr
c
pr871
fuente
fuente
Respuestas:
Larga historia corta:
La promoción de enteros a 16 bits siempre tiene lugar; el estándar C lo impone. Pero el compilador puede optimizar el cálculo de nuevo a 8 bits (los compiladores de sistemas integrados suelen ser bastante buenos en tales optimizaciones), si puede deducir que el signo será el mismo que hubiera sido si el tipo hubiera sido promovido.
¡Este no es siempre el caso! Los cambios de firma implícitos causados por la promoción de enteros son una fuente común de errores en los sistemas integrados.
Puede encontrar una explicación detallada aquí: Reglas de promoción de tipo implícito .
fuente
como se esperaba fun1 es todo ints también lo hace la matemática de 16 bits
Aunque técnicamente es incorrecto, ya que es una adición de 16 bits invocada por el código, incluso sin optimizar este compilador eliminó el adc debido al tamaño del resultado.
No estoy realmente sorprendido de que ocurra la promoción, los compiladores no solían hacer esto, no estoy seguro de qué versión hizo que esto comenzara a ocurrir, me encontré con esto al principio de mi carrera y, a pesar de que los compiladores promocionan fuera de servicio (al igual que arriba), realicé la promoción a pesar de que yo Le dije que hiciera matemáticas uchar, no sorprendido.
y lo ideal, sé que es de 8 bits, quiero un resultado de 8 bits, así que simplemente le dije que hiciera 8 bits hasta el final.
Por lo tanto, en general, es mejor apuntar al tamaño del registro, que es idealmente el tamaño de un (u) int, para un mcu de 8 bits como este, los autores del compilador tuvieron que comprometerse ... El punto es no tener el hábito de el uso de uchar para matemáticas que usted sabe no necesita más de 8 bits, como cuando mueve ese código o escribe un código nuevo como ese en un procesador con registros más grandes, ahora el compilador tiene que comenzar a enmascarar y extender signos, lo que algunos hacen de forma nativa en algunas instrucciones, y otros no.
Forzar 8 bit cuesta más. Hice trampa un poco / mucho, necesitaría ejemplos un poco más complicados para ver más de esto de una manera justa.
EDITAR basado en comentarios discusión
No sorpresa. Aunque, ¿por qué el optimizador dejó esa instrucción extra, no puedes usar ldi en r19? (Sabía la respuesta cuando la pregunté).
EDIT2
para avr
para evitar el mal hábito o no la comparación de 8 bits
claramente la optimización estaba activada solo toma un segundo para probar con su propio compilador para ver cómo se compara con mi salida, pero de todos modos:
Y sí, usar bytes para variables de tamaño de byte, ciertamente en un avr, pic, etc., le ahorrará memoria y realmente desea tratar de conservarlo ... si realmente lo está usando, pero como se muestra aquí, lo menos posible es va a estar en la memoria, tanto como sea posible en los registros, por lo que el ahorro flash se produce al no tener variables adicionales, el ahorro de memoria RAM puede o no ser real.
fuente
unsigned char
modo que tiene para llevar a cabo la promoción de 16 bits, según sea necesario por el estándar(a<<8)|b
siempre es incorrecto para cualquier sistema conint
16 bits.a
será promovido implícitamente a loint
que está firmado. En caso de tenera
un valor en el MSB, terminas cambiando esos datos al bit de signo de un número de 16 bits, lo que invoca un comportamiento indefinido.No necesariamente, ya que los compiladores modernos hacen un buen trabajo al optimizar el código generado. Por ejemplo, si escribe
z = x + y;
dónde están todas las variablesunsigned char
, se requiere que el compilador las promuevaunsigned int
antes de realizar los cálculos. Sin embargo, dado que el resultado final será exactamente el mismo sin la promoción, el compilador generará código que solo agrega variables de 8 bits.Por supuesto, este no es siempre el caso, por ejemplo, el resultado
z = (x + y)/2;
dependería del byte superior, por lo que la promoción tendrá lugar. Todavía se puede evitar sin recurrir al ensamblaje volviendo a arrojar el resultado intermediounsigned char
.Algunas de estas ineficiencias pueden evitarse utilizando las opciones del compilador. Por ejemplo, muchos compiladores de 8 bits tienen un pragma o un conmutador de línea de comandos para ajustar los tipos de enumeración en 1 byte, en lugar de
int
lo requerido por C.fuente
int
, yachar
que probablemente no tendrá el mismo rango de conversión queint
en cualquier plataforma.int
(sí, es inconsistente). C11 6.7.2.2Each enumerated type shall be compatible with char, a signed integer type, or an unsigned integer type. The choice of type is implementation-defined...