C preprocessor concatenation

How to combine predefined C values ​​to generate a string.

#define APP_NUMBER 22 #define ICON_FILE "../icons/"##APP_NUMBER##".ico" 

so in my .rc file i can do the following

  1000 ICON ICON_FILE 

instead of 1000 ICON "../icons/22.ico"

he did not work

  #define MY_ICON_FILE 25 #define STR(x) #x #define ICON_FILE_NUM(x) "../icons/" STR(x) ".ico" 1000 ICON ICON_FILE_NUM(MY_ICON_FILE) 

compiler error

  can't open icon file `../icons/': Permission denied nothing was appended to "../icons/" 

The closest I just got is:

  #define MY_ICON_FILE 25 #define STR(x) #x #define ICON_FILE_NUM(x) "../icons/"STR(x)".ico" /// took out spaces 1000 ICON ICON_FILE_NUM(MY_ICON_FILE) 

(taking out the spaces around STR (x))

and got this compiler error

  can't open icon file `../icons/"25".ico': Invalid argument 
+4
source share
4 answers

It works:

 #define APP_NUMBER 22 #define STR(x) #x #define ICON_FILE_NAME(num) "../icons/" STR(num) ".ico" #define ICON_FILE ICON_FILE_NAME(APP_NUMBER) #include <stdio.h> int main(void) { printf("ICON_FILE = \"%s\"\n", ICON_FILE); return 0; } 

Output:

 ICON_FILE = "../icons/22.ico" 

But the ICON_FILE macro expands to "../icons/" "22" ".ico" , which is a valid syntax for C (adjacent string literals are combined), but probably not for the .rc file, which explains that "cannot be opened icon file, the message you receive.

It looks like you are trying to use token-pasting to create a string literal. The problem is that a partial string literal containing the unsurpassed character " cannot be a valid preprocessing token. For example, you cannot pass one " as an argument to a macro.

Consider writing a program (script, independently) that generates the appropriate #define directives for you.

+3
source

Windows resource files do not understand the concatenation of C-style literal strings for most elements. The only exception may be the row table.

The trick when working with preprocessor macros is to not use strings as the starting point of input, the preprocessor does not know how to remove quotes.

It would be useful to concatenate only once - consider adding search paths "-I../icons/" instead of adding paths to resource names.

Called the following from boost, for example, using Windows msvc, which uses an additional level of indirection than what I saw in most places.

 # define BOOST_PP_CAT(a, b) BOOST_PP_CAT_OO((a, b)) # define BOOST_PP_CAT_OO(par) BOOST_PP_CAT_I ## par # define BOOST_PP_CAT_I(a, b) a ## b # define BOOST_PP_STRINGIZE(text) BOOST_PP_STRINGIZE_A((text)) # define BOOST_PP_STRINGIZE_A(arg) BOOST_PP_STRINGIZE_I arg # define BOOST_PP_STRINGIZE_I(text) #text 

In the examples, you can simply do BOOST_PP_CAT(../icons/, BOOST_PP_CAT(num,.ico))

There is a problem with the string only the external CAT is applied (at least in windows). So BOOST_PP_STRINGIZE(BOOST_PP_CAT(../icons/, BOOST_PP_CAT(num,.ico))) does not work.

3 Concatenation Supplement

 # define BOOST_PP_CAT2(a, b, c) BOOST_PP_CAT_OO2((a, b, c)) # define BOOST_PP_CAT_OO2(par) BOOST_PP_CAT_I2 ## par # define BOOST_PP_CAT_I2(a, b, c) a ## b ## c 

In my testing VS2013 input

  • .. converted to "..." , which makes working with a relative path difficult
  • \ must be escaped \\ to work in args macros, but converted to "\\" - using / for the path works better

Working with a row table may be easier to see the output than working with icons

 STRINGTABLE BEGIN 123 BOOST_PP_STRINGIZE(BOOST_PP_CAT(APP_NUMBER, .ico)) 124 BOOST_PP_STRINGIZE(BOOST_PP_CAT2(../icons/, APP_NUMBER,.ico))) END 

I have not yet developed permission ... to convert to ... I had the following work using an additional search path,

 1000 ICON BOOST_PP_STRINGIZE(BOOST_PP_CAT(APP_NUMBER, .ico)) 1001 ICON BOOST_PP_STRINGIZE(BOOST_PP_CAT2(icons/, APP_NUMBER, .ico)) 
+1
source

I would honestly avoid doing this with a preprocessor. Debugging preprocessor errors is a pain, and I saw cases where several levels of preprocessor replacements and concatenations were used, which led to disaster when trying to find problems. Only my 2 cents.

-1
source

I don’t think you can do it with the C preprocessor. However, you can do it with the m4 preprocessor.

 linux_prompt> cat icon.m4 define(APP_NUMBER, 22) 1000 ICON "../icons/APP_NUMBER.ico" linux_prompt> m4 icon.m4 1000 ICON "../icons/22.icon" 

You must ensure that the rest of the file is correctly expanded. Make "man m4" for more information.

-1
source

Source: https://habr.com/ru/post/1447654/


All Articles