¿La mejor manera de definir 2 bytes para un uso fácil con inicialización / comparación de matriz en C?

Again, I am fairly new to C so forgive the simplicity / stupidity of this question. Anyway, here it goes. What is the best way to #define a 2 byte macro (i.e. #define MSGID 0xABCD) in C that is easy to put inside a byte array but also compare the contents of with if statements?

To clarify this, take the 0xABCD example again. Say I want to do an:

unsigned char test_msg[] = { 0x00, 0x01, 0x02, MSGID, 0x03, 0x04, 0x05 };

With how I defined it above, it won't work because it's defined as a large int and gcc truncates it to an unsigned type. When I define it as #define MSGID 0xAB,0xCD it seems to work fine, but I don't understand what the comma does there and that doesn't look very clean. Another option I found that works, but also not clean, is splitting it like #define MSGIDCLASS 0xAB then #define MSGID 0xCD.

I would also like to compare these MSGID bytes and at the moment I'm having to constantly do an if(data[n] == MSGIDCLASS && data[n+1] == MSGID) ... for every message I need to parse and respond to. I was wondering if there was an easier way of doing this, that's all. If not, I'll leave it as is. Thanks again for the help. Sorry for not using the code sample tags, didn't think they were necessary with one liners.

preguntado el 08 de enero de 11 a las 17:01

3 Respuestas

#define's simply get replaced with their contents. So when you use commas the final code becomes:

unsigned char test_msg[] = { 0x00, 0x01, 0x02, 0xAB, 0xCD, 0x03, 0x04, 0x05 };

That's why it seems to work.

Instead, defining MSGIDHI y MSGIDLO components separately allows you to both use and compare easily. And you can define MSGID as:

#define MSGIDLO 0xCD
#define MSGIDHI 0xAB
#define MSGID (MSGIDLO | (MSGIDHI << 8)) 

This way you can use them in any form you want.

Respondido el 08 de enero de 11 a las 20:01

Doh, the #define with the comma makes sense now, as do you suggestions. Thanks though, this is perfect, just what I was looking for! Appreciate the prompt reply and suggestions. - gato

Sometimes you may prefer a solution without a preprocessor instead, like this:

enum {MSGID = 0xABCD};
// in C++ you can use const int MSGID = 0xABCD instead, not sure about C

unsigned char test_msg[] = { 0x00, 0x01, 0x02, MSGID>>8, MSGID&0xff, 0x03, 0x04, 0x05 };

Respondido el 08 de enero de 11 a las 21:01

Thanks! Seeing the different kinds of ways people solve problems here makes it worth it asking the question, no matter how simple it is :) - gato

If your message-ID's are really composed of a Class and an ID, and that separation is not just made to split them into two bytes, then you could do the following:

  • Keep the separate class and ID values
  • Use those separate val;ues to fill in in the messages
  • Use the following macros to compare them:

    #define MSGID(msgClass, ID) (((msgClass) << 8) | (ID))
    #define GET_MSGID(data, n) (((data)[n] << 8) | (data)[(n)+1])
    

Los usas así:

#define MSGCLASS_A 0xAB
#define MSGID_B    0xCD

unsigned char test_msg[] = { 0x00, 0x01, 0x02, MSGCLASS_A, MSGID_B, 0x03, 0x04, 0x05 };

if (GET_MSGID(test_msg, 0) == MSG_ID(MSGCLASS_A, MSGID_B))
{
  // matched message
}

If your message-ID's are really just a 16-bit number, you could do the following:

  • Use a single define for your message-ID's
  • Use the following macros to insert/extract them from a message:

    #define MSGID(ID) (((ID) >> 8) & 0xFF), ((ID) & 0xFF) /* For static message definitions */
    #define ADD_MSGID(data, n, ID) do { (data)[n] = (((ID) >> 8) & 0xFF; (data)[(n)+1] = ((ID) & 0xFF; } while (0)
    #define GET_MSGID(data, n) (((data)[n] << 8) | (data)[(n)+1])
    

Los usas así:

#define MSGID_A 0xABCD

unsigned char test_msg[] = { 0x00, 0x01, 0x02, MSGID(MSGID_A), 0x03, 0x04, 0x05 };

// or: ADD_MSGID(test_msg, 0, MSGID_A)

if (GET_MSGID(test_msg, 0) == MSGID_A)
{
  // matched message
}

La coma en el MSGID macro is handled just like any comma separating initialisers for an array, because macros just perform a textual replacement before the compiler parses the code.

Respondido el 08 de enero de 11 a las 21:01

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.