TRUE / FALSE o true / false?

3

En sistemas con recursos limitados (como un PIC de 8 bits), ¿hay algún beneficio en usar sus propias macros para verdadero y falso en lugar de usar los definidos en stdbool?

#define TRUE    (1)
#define FALSE   (0)

// OR (dummy example)
#include <stdbool.h>

bool IsThisGood(void)
{
  return true | false;
}

uint8_t IsThisBetter(void)
{
  return TRUE | FALSE;
}

¿Cómo se comparan en términos de uso de RAM? Uso de la pila? Código de portabilidad? Código de simplicidad?

    
pregunta tarabyte

4 respuestas

4
  

En sistemas con recursos limitados (como un PIC de 8 bits), ¿hay algún beneficio en usar sus propias macros para verdadero y falso en lugar de usar los definidos en stdbool?

Las macros son evaluadas por el pre-compilador antes del tiempo de compilación, no por el compilador o micro en tiempo de ejecución. Una macro definida como "1" se reemplazará por "1" antes de que el compilador empiece a intentar averiguar cómo optimizar su código. A menos que su macro sea mejor que la macro stdbool, no hay beneficio.

  

¿Cómo se comparan en términos de uso de RAM? Uso de la pila?

1 == 1, independientemente de cómo se define la macro. No hay diferencia.

  

¿Portabilidad de código?

Al usar macros no estándar, la portabilidad del código sufre. Su código necesitará sus definiciones / encabezados, por lo que alguien no puede copiar y pegar una sección que parece estándar sin obtener errores. Especialmente con algo como "Verdadero" o "Falso".

  

¿Simplicidad de código?

Si no necesitas todos los stdbool, seguro, definir el tuyo puede ser más simple. Eso es realmente una cuestión de opinión.

Actualización:

  

En cuanto al uso de la pila, quiero preguntar ¿qué se devuelve en cada caso? 8bits? 16bits? Registrar el tamaño del microcontrolador?

Esta es una mejor pregunta. Es un poco complicado. Primero, "bool" es realmente una macro para "_Bool", un tipo de datos c99. Normalmente, _Bool es el objeto direccionable más pequeño capaz de contener un 0 o un 1. Es un char, un objeto de 8 bits. (Las cosas como los nibbles son objetos demasiado complicados que requieren un código de fondo para dividir un solo carácter de 8 bits en dos objetos "separados" de 4 bits). _Bool también tiene algo de lógica en donde es 0 cuando 0, o 1 cuando algo sobre o debajo de 0. _bool random_variable = 5 daría como resultado una variable aleatoria igual a 1. En cuanto a la memoria, ese valor será de 8 bits, pero devolverá el literal 0 o 1.

Segundo, verdadero y falso, como ha creado la macro para, son exactamente lo mismo que stdbool.h define verdadero y falso. Un 0 o 1 literal. Los intergers literales son, por defecto, los tipos de datos int . int no es un estándar fijo. Puede ser definido por su IDE, compilador o idioma. Cambia según el fabricante del microcontrolador o incluso la línea de microcontroladores del mismo fabricante. También puede estar firmado o sin firmar por los mismos motivos (consulte: enlace ) Entonces, a menos que si escribes una variable cuando asignas true o false , se enviará a int. Pero uint8_t es un tipo de datos stdint.h sin firma de 8 bits también.

Tercero, tus dos funciones no son exactamente iguales. Tenga en cuenta que IsThisGood devuelve un tipo bool (really _Bool) (objeto char / 8 bit). IsThisBetter devuelve un tipo uint8_t (8 bits). En la práctica, lo mismo, pero el tipo _Bool tiene lógica para hacer algo mayor que 0 = 1, mientras que uint8_t no lo hace. IsThisBetter técnicamente podría devolver 255 por alguna razón.

Finalmente, si por alguna razón "char" en tu microcontrolador / ide / compiler / language es mayor que 8 bits, entonces tu versión uint_8 será más pequeña, en cuanto a memoria, pero aún carecerá de la lógica "mayor que 0 = 1" .

Vea esta respuesta de desbordamiento de pila en el tamaño de _Bool: enlace

    
respondido por el Passerby
3

Para responder a esta pregunta, debe investigar cómo su compilador incorporado implementa el tipo _Bool , que se introdujo en la revisión de 1999 del estándar ISO C. El símbolo _Bool es en realidad una palabra clave, como static o int ; se introdujo una palabra clave que comienza con un guión bajo y una letra mayúscula para evitar la coincidencia con innumerables programas que ya definen identificadores como bool o BOOL por sí mismos. Cuando incluye el encabezado <stdbool.h> , obtiene un tipo bool que es un sinónimo de bool y las constantes true y false .

Si el tipo _Bool ocupa más de un byte, en su lugar puede haber una ventaja al usar su propio tipo.

Aunque en estructuras y uniones, puede reducir el almacenamiento para los campos estándar bool convirtiéndolos en miembros de campo de bits (por ejemplo, struct foo { bool x : 1, y : 1; } ), no puede hacer eso en otras situaciones: como Variables locales o matrices. Si bool tiene un ancho de dos bytes, entonces bool x[32] tendrá un ancho de 64 bytes, mientras que BOOL x[32] puede tener un ancho de 32 bytes, con su propia definición de BOOL como typedef para char . Aún conservas la opción de redirigir tu BOOL al C99 bool , en un entorno donde tenga sentido.

Si la matriz aún es demasiado grande, tendrá que convertirla en una matriz de unsigned char o unsigned int y paquetes de bits con desplazamiento y enmascaramiento (a costa del aumento del tamaño del código).

Puede experimentar y ver el código generado de la máquina para ver si el código tiene gusto

x = true; // where x is of bool type

genera el mismo código, o código que es más o menos compacto que:

x = TRUE;  // where x is of a type compatible with char, and TRUE expands to 1.

Borrar un byte podría fácilmente requerir más instrucciones o una mayor instrucción en alguna máquina que solo trata con palabras: cargue una palabra en la memoria, establezca la parte apropiada de la misma al valor del byte, luego almacene la palabra completa, en lugar de simplemente almacenar una palabra cero en la memoria. Por lo tanto, puede ganar al ahorrar espacio en las matrices de bools, pero perder en el tamaño del código y en los ciclos. Debe observar el código generado y el diseño de los datos.

Una cosa más: ten cuidado con la alineación. El relleno debido a la alineación puede anular los ahorros de espacio que espera al elegir el tipo de datos. En una estructura, coloque primero los miembros con los requisitos de alineación más estrictos, seguidos de los miembros menos estrictos. En esta situación, no se requiere relleno, incluso si el compilador alinea los miembros de la estructura, excepto posiblemente al final de la estructura. Es decir, evitar struct foo { char c1; int a; char c2; int b; } . Después de cada char , probablemente habrá un relleno para alinear el int . Si la estructura está ordenada como struct foo { int a, b; char c1, c2; } , probablemente será lo más pequeña posible en la mayoría de los compiladores existentes. En el peor de los casos, la estructura en su conjunto tendrá un requisito de alineación que es el mismo que el de su miembro más estrictamente alineado (en este caso, int ) que puede traducir el relleno al final, después de c2 .

    
respondido por el Kaz
2

No habrá diferencia en el uso de RAM o pila, ya que los valores de TRUE , true , false y FALSE serán reemplazados por los enteros apropiados antes de que comience la compilación.

Las respuestas a sus últimas dos preguntas parecen estar basadas en opiniones. En mi opinión, es mejor usar un archivo de encabezado estándar cuando sea posible. Podría argumentar que esta opción hace que el código sea menos portátil, pero creo que mejora la simplicidad del código y elimina cualquier pregunta sobre si ha definido TRUE para ser diferente de true por alguna razón.

    
respondido por el Joe Hass
1

Si incluye stdbool.h , obtiene la macro bool que se expande a _Bool (palabra clave estándar C), y las macros true y false , que se expanden a 1 y 0 , que son literales enteros del tipo int .

  

¿Cómo se comparan en términos de uso de RAM? Uso de la pila?

Como ya se mencionó en otra respuesta, el tipo estándar bool tiene una mejor oportunidad de optimizarse en un campo de bits. Mientras que un typedef uint8_t BOOL siempre será de 8 bits. Por lo tanto, existe la posibilidad de que bool consuma un poco menos de memoria, aunque lo más probable es que esta optimización no se realice y no sea importante para su programa.

  

¿portabilidad de código?

stdbool.h y el tipo _Bool se introdujeron en C con el estándar C99. Si está utilizando un compilador antiguo, puede tener problemas de compatibilidad. Sería particularmente precavido si usara algún compilador MPLAB, se sabe que tienen un bajo estándar de cumplimiento en general.

  

¿Simplicidad de código?

bool , true y false son preferibles, porque son estándar.

BOOL, TRUE y FALSE indican que el código es antiguo y se escribió para C90. O quizás que el programador es viejo y está desactualizado :)

    
respondido por el Lundin

Lea otras preguntas en las etiquetas