Quiero ensamblar una matriz de caracteres que contenga un byte con un valor constante de tiempo de compilación y una cadena, que también es una constante de tiempo de compilación. La solución sería:
char packet[] = "\x42" __DATE__;Eso funciona, pero no es muy legible ni fácil de mantener, ya que 0x42 es un código de operación de mensaje que se usa en otros lugares, lo que lo convierte en un número mágico. Ahora, podría poner una x ficticia en la cadena y seguir esta definición con una tarea como esta:
#define OPCODE 0x42 char packet[] = "x" __DATE__; packet[0] = OPCODE;Pero tengo la sensación de que podría hacerse en un literal de cadena puramente constante, simplemente no puedo encontrar cómo hacerlo. ¿Alguna idea?
__DATE__ debe tener en su mayoría exactamente el formato Mmm dd yyyy , por lo que 11 caracteres. Puedes hacerlo:
char packet[] = { OPCODE, __DATE__[0], __DATE__[1], __DATE__[2], __DATE__[3], __DATE__[4], __DATE__[5], __DATE__[6], __DATE__[7], __DATE__[8], __DATE__[9], __DATE__[10], __DATE__[11], 0, };Como el preprocesador C no puede ayudar aquí, este podría ser un caso para agregar un preprocesador adicional al sistema de compilación.
Ya sea que elija una segunda etapa del preprocesador C, m4, un script de shell o python o cualquier otra cosa, depende de usted.
O toma otra ruta y cambia el tipo de paquete de una matriz de caracteres a una struct con un miembro de matriz flexible, algo como lo siguiente:
/* foo.c * Compile with something like * avr-gcc -mmcu=atmega328 -Os -Wall -Wextra -Werror \ * -save-temps=obj -Wa,-adhlns=foo.lst,-gstabs -c foo.c */ #include <stddef.h> #include <stdint.h> #include <avr/pgmspace.h> #define OPCODE_DATE 0x42 struct packet_descr { uint8_t opcode; uint16_t size; }; struct string_packet { struct packet_descr descr; char string[]; }; #define STRING_PACKET_P(IDENTIFIER, OPCODE, STRING) \ const struct string_packet IDENTIFIER PROGMEM = { \ { (OPCODE), \ sizeof(STRING)-1 \ }, \ (STRING) \ } STRING_PACKET_P(packet_date_P, OPCODE_DATE, __DATE__); void uart_send_char(const char ch); void uart_send_char(const char ch) { UDR0 = ch; } /* Send string packet in the following format: * uint8_t opcode; * uint16_t len; // in AVR endianness * char string[len]; // string of "len" characters, unterminated */ extern void string_packet_send_P(const struct string_packet *string_packet_P); void string_packet_send_P(const struct string_packet *string_packet_P) { const uint8_t opcode = pgm_read_byte(&string_packet_P->descr.opcode); uart_send_char(opcode); size_t len = pgm_read_word(&string_packet_P->descr.size); for (PGM_P byte_P = (PGM_P)&string_packet_P->string; len > 0; len--, byte_P++) { uart_send_char(pgm_read_byte(byte_P)); } } int main(void) { string_packet_send_P(&packet_date_P); return 0; } Una desventaja obvia de una struct con un miembro de matriz flexible es que sizeof(packet) solo producirá el tamaño de la parte que no es de matriz. Sin embargo, dependiendo del formato real de su paquete (el receptor del paquete también necesita saber cuándo comienza y termina un paquete, ¿verdad?), podría ser factible registrar el tamaño por separado.