C Preprocessor: Stringify int with leading zeros?
Asked Answered
K

2

5

I've seen this topic which describes the "stringify" operation by doing:

#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)

#define MAJOR_VER 2
#define MINOR_VER 6
#define MY_FILE "/home/user/.myapp" STR(MAJOR_VER) STR(MINOR_VER)

Is it possible to stringify with leading zeros? Let's say my MAJOR_REV needs to be two characters "02" in this case and MINOR_REV 4 characters "0006" If I do:

#define MAJOR_VER 02
#define MINOR_VER 0006

The values will be treated as octal elsewhere in the application, which I don't want.

Krp answered 17/2, 2015 at 21:35 Comment(4)
My gut feel is it will be sufficiently hard, even with Boost::Preprocessor, that it is not really worth doing. Define MAJOR_VER_STR and MINOR_VER_STR as strings with leading zeros. You could create a script to set major and minor version and the matching strings: setversion --major=2 --minor=7 header.h which does the job.Martinic
It could be done with Boost.Preprocessor, but I believe you'd have to tie up "slots" to do it. It could be done more simply if the initial number format was different such as #define MAJOR_VER (1)(0) for major version 10.Gare
Is it mandatory for you to use the preprocessor? Couldn't you write regular C code for it? Sorry if this is a silly question.Ithaca
Looking at your example, you intend to "version" a configuration file. This is not commonly done. Perhaps you're trying to solve a problem that would better be solved by a smart handling of the config file format, so myapp doesn't spam config files with every update? I cannot imagine the user will enjoy having to reconfigure myapp with every minor update...Instrument
P
7

No clean nor handy way to do it. Just as a challenge, here a possible "solution":

1) create a header file (e.g. "smartver.h") containing:

#undef SMARTVER_HELPER_
#undef RESVER
#if VER < 10
#define SMARTVER_HELPER_(x) 000 ## x
#elif VER < 100
#define SMARTVER_HELPER_(x) 00 ## x
#elif VER < 1000
#define SMARTVER_HELPER_(x) 0 ## x
#else
#define SMARTVER_HELPER_(x) x
#endif
#define RESVER(x) SMARTVER_HELPER_(x)

2) In your source code, wherever you need a version number with leading zeroes:

#undef VER
#define VER ...your version number...
#include "smartver.h"

at this point, the expression RESVER(VER) is expanded as a four-digit sequence of character, and the expression STR(RESVER(VER)) is the equivalent string (NOTE: I have used the STR macro you posted in you answer).

The previous code matches the case of minor version in your example,it's trivial to modify it to match the "major version" case. But in truth I would use a simple external tool to produce the required strings.

Ploughshare answered 18/2, 2015 at 9:20 Comment(0)
P
0

I believe in the example provided by the question sprintf is the correct answer.

That said, there are a few instances where you really want to do this and with C preprocessor if there is a will and somebody stupid enough to write the code there is typically a way.

I wrote the macro FORMAT_3_ZERO(a) which creates a three digit zero padded number using brute force. It is in the file preprocessor_format_zero.h found at https://gist.github.com/lod/cd4c710053e0aeb67281158bfe85aeef as it is too large and ugly to inline.

Example usage

#include "preprocessor_format_zero.h"

#define CONCAT_(a,b) a#b
#define CONCAT(a,b) CONCAT_(a,b)

#define CUSTOM_PACK(a) cp_ ## a __attribute__( \
        (section(CONCAT(".cpack.", FORMAT_3_ZERO(a))), \
        aligned(1), used))

const int CUSTOM_PACK(23);
Ptolemaist answered 15/2, 2017 at 6:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.