1

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.

3 Answers 3

3

#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 and 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.

Sign up to request clarification or add additional context in comments.

1 Comment

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.
1

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 };

1 Comment

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

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])
    

You use them like this:

#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])
    

You use them like this:

#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
}

The comma in the 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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.