2

The version number in my code is defined in a few formats which requires me to change more than one definition when I go up in the version:

#define VERSION_N       0x0203
#define SERIALNUMBER_STR    L"2.0.3"

and so on.

I'd like to centralize it to one single definition. Something like:

#define VER_X_  0
#define VER_H_  2
#define VER_M_  0
#define VER_L_  3

#define VERSION_N   VER_L_ + 0x10*VER_M_ + 0x100*VER_H_ + 0x1000*VER_X_
#define SERIALNUMBER_STR    ??????????????
4
  • You should put parentheses around your macro bodies to prevent surprises due to operator precedence at the expansion site. i.e. 2*VERSION_N will give you the wrong result because it will only multiply the VER_L_ by 2 since * has higher precedence than +. Commented Mar 2, 2014 at 22:27
  • @pat Interesting. Should be put in the final solution though irrelevant in my case. Tx. Commented Mar 3, 2014 at 8:22
  • Who started the obsession with trailing underscores in macro names? Commented May 14, 2016 at 9:23
  • @Shaul the currently accepted answer (written by you) is misleading and even after the edits back in 2014 it is still incorrect. The other answer by ouah is the best -- please consider accepting that answer instead, to assist future visitors to Stack Overflow. Commented Mar 26, 2021 at 1:45

2 Answers 2

3

Use a stringify macro:

#define STRINGIFY_1(x...)   #x
#define STRINGIFY(x...)     STRINGIFY_1(x)

#define VER_X_  0
#define VER_H_  2
#define VER_M_  0
#define VER_L_  3

#define SERIALNUMBER_STR  STRINGIFY(VER_H_) L"." STRINGIFY(VER_M_)  \
                          L"." STRINGIFY(VER_L_)

EDIT1: I added the L in L"." to have wide strings. I don't put a L#x as it got expanded with a space and something in the form L "string" is not a string literal in C. Nevertheless concatenating a string literal and a wide string literal result in a wide string literal.

EDIT2: As put in the comments, the example above work with the last revisions of C (c99 and c11) but not with c89 (i.e., not with MSVC). First reason is variadic macros are not supported in c89. The second reason is in c99 you can concatenate a character string literal and a wide string literal but in c89 this is undefined behavior. Below is a standard solution that also work in c89:

#define CAT(x, y)  x##y
#define WIDE(x)    CAT(L,x)

#define STRINGIFY_1(x)   #x
#define STRINGIFY(x)     STRINGIFY_1(x)

#define VER_X_  0
#define VER_H_  2
#define VER_M_  0
#define VER_L_  3

#define SERIALNUMBER_STR  WIDE(STRINGIFY(VER_H_)) L"." WIDE(STRINGIFY(VER_M_))  \
                          L"." WIDE(STRINGIFY(VER_L_))
Sign up to request clarification or add additional context in comments.

4 Comments

Not compiling. Perhaps not supported by MS (I'm using Build 6.0) Also, I need a wide char string.
@Shaul MSVC does not support c99, remove the ... in the macro and it will work with MSVC.
MS did not accept the change. Error message is: error C2308: concatenating mismatched strings.
@Shaul another c89 issue. Concatenating wide string literal and character string literal is OK in c99 (and the result is a wide string literal) but is undefined behavior in c89.
0

Here's the tested solution:

#define VER_X_  0
#define VER_H_  2
#define VER_M_  0
#define VER_L_  3



#define VERSION_N (VER_L_ + 0x10*VER_M_ + 0x100*VER_H_ + 0x1000*VER_X_)

// Device Strings
//
#define STRINGIFY_1(x)   L#x
#define STRINGIFY(x)     STRINGIFY_1(x)
#define PASTE(x, y) x##y
#define MAKEWIDE(x) PASTE(L,x)

#define SERIALNUMBER_STR MAKEWIDE(STRINGIFY(VER_H_)) L"." \
                         MAKEWIDE(STRINGIFY(VER_M_)) L"." \
                         MAKEWIDE(STRINGIFY(VER_L_))

Thanks to ouah

EDIT:

  1. Added parentheses according to pat.
  2. Ouah's remark was taken seriously. Solution adapted to suit MS: Added two PASTE & MAKEWIDE

2 Comments

see the edit in my answer for wide strings, you should not use L#x.
Just my personal taste, but I find the original two macros better in any way. What you ended up with is a lot of obfuscation.

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.