-1

So I need/want a C/C++ macro function that takes a #define constant and converts it into a hex string. I know that # does it but not exactly what I want.

Here's basically what I have now:

#define SHIFT 2
#define CONSTANT 0x00000001 << SHIFT

#define _MAKE_HEX(value) #value
#define MAKE_HEX(value) _MAKE_HEX(value)

const char* String = MAKE_HEX(CONSTANT);

The result is not the final value and it just shows the result of the text substitution. How can I fix this?

Caleb Merchant
  • 289
  • 1
  • 5
  • 16
  • There's no such functionality in C or C++. – Sam Varshavchik Jul 30 '15 at 01:36
  • C is **not** C++ is **not** C. Choose one language; – too honest for this site Jul 30 '15 at 01:36
  • In C++, you may use template with meta programming. – Jarod42 Jul 30 '15 at 01:37
  • 1
    You should read about the purpose of macros. They are **for text substitution** – too honest for this site Jul 30 '15 at 01:37
  • There's no easy way but I suspect you could accomplish it with [clever use of recursion](http://stackoverflow.com/questions/319328/writing-a-while-loop-in-the-c-preprocessor). Is there a reason you need the value as both a string and integer literal? My recommendation would be to just generate the string version at runtime. – MooseBoys Jul 30 '15 at 01:39
  • How come the first two lines of the code-snippet into play? I do not see where you actually use the macros. – too honest for this site Jul 30 '15 at 01:39
  • @Olaf I added another line now. – Caleb Merchant Jul 30 '15 at 02:01
  • @MooseBoys I do actually need both the integer value and the hex value. I use the integer value for an error code. Then I have an error message lookup table that I use the hex string value in. This macro is not imperative that it gets done but it would make my life easier because I wouldn't have to to copy and past 100 different error code values into a string and hope I didn't mess up. – Caleb Merchant Jul 30 '15 at 02:03
  • You shortening was to rigid apparently. Please provide a [mcve] And you still should **pick one language**! – too honest for this site Jul 30 '15 at 02:06
  • 2
    @Olaf Yes I know C and C++ aren't the same language but macros behave very similarly in both languages. – Caleb Merchant Jul 30 '15 at 02:08
  • There is something I am not getting. If you have the integer value, can't that be used to subscript into the error message lookup table? Then in the message use %02X as a format to printf the integer value out as a hex value. Humm. show us a small error message array, and show us what you want your output to look like. – EvilTeach Jul 30 '15 at 02:11
  • As you see already, there are different approaches for both languages. Fine, if you are asking for a **macro**, the answer is: **NO**. But there might be another solution which is **langauge specific**. Heck, do you want a macro or a solution for your problem? – too honest for this site Jul 30 '15 at 02:13
  • @EvilTeach I'm not using printf (except for debugging obviously). I'm doing error logging. And I don't use C/C++ library functions for my file IO. I use the Windows functions which means I need to have everything in a buffer. Yes I could do message formatting like you are talking about but there's a reason I'm using an error lookup table. It's a large program with a lot going on and I don't really have time to format a string every time I send a message. – Caleb Merchant Jul 30 '15 at 02:14
  • every time you send a message, you pass an integer into a function, which does the lookup to get the message, appends %02x or whatever, executes the sprintf, and sends the result off to your logging subsystem – EvilTeach Jul 30 '15 at 02:18
  • @Olaf I don't have to use a macro. And if somebody has a solution for either language (even if it is language specific) it will work fine. If it isn't a macro though I might as well make a function that formats the string during startup time and hope the optimizer optimizes it out in release mode. – Caleb Merchant Jul 30 '15 at 02:18
  • @EvilTeach Honestly you're probably right. As long as I have each string in the lookup table the right size I can call sprintf or whatever to format the string. That shouldn't be a problem at all. Because the buffer is already allocated sprintf or whatever wouldn't take up hardly any time at all. – Caleb Merchant Jul 30 '15 at 02:27
  • Please edit your question to show the expected output for this code – M.M Jul 30 '15 at 04:16

2 Answers2

2

Well... if you can define SHIFT as the actual zeros needed rather than the number of them, then you could do this:

#define SHIFT 00
#define ONE 0x1

#define _MAKECONSTANT(value, shift) value ## shift
#define MAKECONSTANT(value, shift) _MAKECONSTANT(value, shift)

#define CONSTANT MAKECONSTANT(ONE, SHIFT)

#define _MAKE_HEX(value) #value
#define MAKE_HEX(value) _MAKE_HEX(value)

const char* String = MAKE_HEX(CONSTANT);
int value = CONSTANT;

The string ends up as "0x100" and the integer as the intended value.

TheUndeadFish
  • 8,058
  • 1
  • 23
  • 17
  • Wow. Good thought. I Like it! This is perfect because in my code I'm not using a shift but I'm using a bitwise OR. Example: 0x12340000 | 0x00005678. So now I could do exactly what you have above. – Caleb Merchant Jul 30 '15 at 03:55
  • 1
    @CalebMerchant why don't you make your question ask about what you are actually doing, instead of some partially related question? – M.M Jul 30 '15 at 04:19
0

In C++14, you may do something like

template <std::size_t N>
constexpr char bin_string[] = {'0', 'b',
    ((N >> 7) & 1) ? '1' : '0',
    ((N >> 6) & 1) ? '1' : '0',
    ((N >> 5) & 1) ? '1' : '0',
    ((N >> 4) & 1) ? '1' : '0',
    ((N >> 3) & 1) ? '1' : '0',
    ((N >> 2) & 1) ? '1' : '0',
    ((N >> 1) & 1) ? '1' : '0',
    ((N >> 0) & 1) ? '1' : '0',
    '\0'
}; 

template <std::size_t N>
constexpr char hex_string[] = {'0', 'x',
    "0123456789ABCDEF"[(N >> 8u) & 0x0F],
    "0123456789ABCDEF"[(N >> 0u) & 0x0F],
    '\0'
}; 

Live demo

Jarod42
  • 203,559
  • 14
  • 181
  • 302