7

I want to declare a static const array, which contains string with version info.

I already have two macros with version numbers and I want to generate an initial const string based on it.

I am trying to use the approach described here, but it does not work as it is expected with available compiler tools.

My code is next:

#define API_VERSION_MAJOR 4
#define API_VERSION_MINOR 47

#define _STR(x) #x
#define STR(x) _STR(x)

static const char OSAPIVersion[] =
    STR(API_VERSION_MAJOR) "." STR(API_VERSION_MINOR) ;

When I print the array, its value is "API_VERSION_MAJOR.API_VERSION_MINOR" instead of "4.47".

I use a customized GCC 4.4.1 ARM cross-compiler.

When I do the same on my PC with Cygwin GCC 4.5.3, it works.

Thank you in advance for your help.

UPDATE:

It turned out that API_VERSION_MAJOR and API_VERSION_MINOR macros were unvisible in a source file. I just missed the include. So simple. Too simple to be obvious.

Note that there is not any warning output in this case.

Community
  • 1
  • 1
yurko
  • 623
  • 1
  • 7
  • 21
  • 4
    Totally unrelated to your problem, but don't use symbol names with a leading underscore followed by an upper-case letter, as those are reserved for the "implementation" (i.e. compiler and standard library). – Some programmer dude Apr 21 '16 at 09:14
  • 3
    Just tried the code fragment with gcc 4.4, 4.8 and 4.9, i386, x64 and cross-arm on Ubuntu 12.04 and 14.04 - works as expected (using `compiler -E testfile.c`). I think the problem lies somewhere else. It would be a major bug in a compiler/preprocessor for that to not work otherwise. – Dummy00001 Apr 21 '16 at 09:15
  • Is the posted code copied and pasted from your source file? – LPs Apr 21 '16 at 09:19
  • 1
    Works fine with an online compiler https://ideone.com/InZcfu – Santosh A Apr 21 '16 at 09:20
  • @LPs Yes, this code snippet is from my source file. – yurko Apr 21 '16 at 09:28
  • It seems that your real code is: `static const char OSAPIVersion[] =_STR(API_VERSION_MAJOR) "." _STR(API_VERSION_MINOR) ;` – LPs Apr 21 '16 at 09:29
  • 1
    Are you sure that `API_VERSION_MAJOR` is available to compilation unit with `OSAPIVersion`? It's in your example, but is it in your real code (if you are using compiler flags to define preprocessor constants, for example)? – user694733 Apr 21 '16 at 09:35
  • @user694733 Yes, it is the case. No bugs in compiler (this time). It is so easy to miss such obvious things. Thank you a lot. – yurko Apr 21 '16 at 10:15
  • 1
    The posted code is not your real code then................. – LPs Apr 21 '16 at 10:27
  • @LPs Yes, my fault. Defines are located in a header file which was not included. I just put it into the example to make it (as I thought) clear. – yurko Apr 21 '16 at 10:30
  • 1
    it is a very poor programming practice to define two different entites, one with a leading underscore and one without. While modern compilers might be able to handle that problem, older compilers will think they are both the same entitiy. This is because, in the process of tokenizing. etc and in the generation of the assembly code, each identifier is pre-pended with one or two underscores. SO the compiler might not be able to differentiate between them. Suggest using unique names and never use leading underscores – user3629249 Apr 21 '16 at 23:21

1 Answers1

7

Then your customized GCC 4.4.1 ARM cross-compiler is buggy.

If you compiled it yourself, sometimes it helps to disable some overly aggressive optimization options that might have not all their kinks ironed out.

Thinking outside the box, you might adjust the source code to avoid the problem:

#define API_VERSION_MAJOR "4"
#define API_VERSION_MINOR "47"
static const char OSAPIVersion[] = API_VERSION_MAJOR "." API_VERSION_MINOR;

or maybe construct the string at run-time:

#define API_VERSION_MAJOR 4
#define API_VERSION_MINOR 47
static char OSAPIVersion[8];
int main(void) {
  snprintf (OSAPIVersion, sizeof OSAPIVersion, "%d.%d", API_VERSION_MAJOR, API_VERSION_MINOR);
}
Jens
  • 69,818
  • 15
  • 125
  • 179