cálculos de tiempo de compilación en C

1

He estado implementando un software de control en lenguaje de programación C. Uno de Los módulos de software representan una tabla de comunicación para algunos propietarios. Protocolo de comunicación. Cada registro en esta tabla tiene un elemento (entre otros) que consta de 8 bits. Este elemento representa las propiedades asociadas a este registro. Cada registro puede tener propiedades dadas a continuación:

reportado, event_logged, time_logged, archivado global

Necesito definir la tabla de comunicación y por razones de legibilidad no lo hago Quiere llenar las propiedades de cada registro con valores 0-31. Mi idea era en primer lugar, defina a continuación las máscaras de bits para bits individuales en las propiedades byte:

#define REPORTED       0x10
#define EVENT_LOGGED   0x08
#define TIME_LOGGED    0x04
#define ARCHIVED       0x02
#define GLOBAL         0x01

Luego quise definir una macro con parámetros que preparen el contenido de las propiedades basadas en valores legibles por humanos

#define Create_properties(reported, event_logged, time_logged, archived, global){ \
  (uint8_t)reported | (uint8_t)event_logged | (uint8_t)time_logged |              \
  (uint8_t)global                                                                 \
}

El uso planificado está siguiendo. Por ejemplo uno de los registros en la comunicación. la tabla se registrará y se registrará el tiempo, así que escribiré la macro de esta manera

Create_properties(0, EVENT_LOGGED, TIME_LOGGED, 0, 0, 0)

y el resultado esperado es 01100. Me he enfrentado a un problema que no tengo. capaz de compilar este código fuente. Siempre recibo error de compilación "llaves alrededor del inicializador escalar". He estado usando el compilador gcc. Hace Alguien sabe por qué se produce este error? Gracias por cualquier idea.

    
pregunta Steve

2 respuestas

1

Las llaves rizadas {} no se utilizan para las definiciones de macro. Intenta eliminarlos y ver si funciona:

#define Create_properties(reported, event_logged, time_logged, archived, global) \
  (uint8_t)reported | (uint8_t)event_logged | (uint8_t)time_logged |              \
  (uint8_t)global    
    
respondido por el Justin
5

Ya que estos son solo números de 8 bits, puede usar una enumeración de forma segura. Elija un prefijo de código que tenga sentido. No sé qué se supone que haga su código, así que utilicé STUFF_ como marcador de posición, para ser reemplazado por un nombre mejor.

enum
{
  STUFF_REPORTED     = 0x10,
  STUFF_EVENT_LOGGED = 0x08,
  STUFF_TIME_LOGGED  = 0x04,
  STUFF_ARCHIVED     = 0x02,
  STUFF_GLOBAL       = 0x01,
};

Luego simplemente crea una macro para cada caso:

#define STUFF_EVENT_TIME_LOGGED ( (uint8_t)(STUFF_EVENT_LOGGED | STUFF_TIME_LOGGED) )

Hacer una macro similar a una función como Create_properties no ofrece ningún beneficio, ya que podría confundirse con una función y tendrá cero seguridad de tipo, lo que hace que sea difícil de leer y peligroso para ambos. Así que no lo recomendaría, las macros similares a funciones deberían evitarse si es posible. Pero, por supuesto, también se puede hacer:

#define Create_properties(reported, event_logged, time_logged, archived, global) \
  (uint8_t) ((reported) | (event_logged) | (time_logged) | (archived) | (global))

Notablemente, sus lanzamientos a uint8_t fueron completamente inútiles, ya que cada operando de | obtendrá un entero ascendido a int de todos modos. Si debe realizar la conversión a algo antes de que se realice el | , debería ser uint32_ . O simplemente puede convertir a uint8_t después de la operación, como en mi macro anterior.
Consulte Reglas de promoción de tipo implícito para obtener más información.

    
respondido por el Lundin

Lea otras preguntas en las etiquetas