C宏 - 如何将整数值转换为字符串文字[重复]

时间:2021-12-22 19:16:14

This question already has an answer here:

这个问题在这里已有答案:

Is it possible to get the value of a #defined integer symbol to be inserted verbatim into a string literal that is part of an assembly section in GCC (AVR Studio)?

是否可以将#defined整数符号的值逐字插入到作为GCC(AVR Studio)中的汇编部分一部分的字符串文字中?

I want the "LEDS" to be replaced by 48 within the string literal inside the asm() block below.

我希望在下面的asm()块内的字符串文字中将“LEDS”替换为48。

#define LEDS 48 //I only want ONE mention of this number in the source
int x = LEDS;   //I'm using the value directly too

void DrawFrame()
{
    asm(
    "ldi        R27, 0x00       \n\t"
    "ldi        R26, 0x00       \n\t"
    "ldi        R18, LEDS       \n\t" //<-- substitution needed here
...
}

But I want the compiler/assembler (after the preprocessor has done it's job) to see this...

但我希望编译器/汇编程序(在预处理器完成它的工作之后)看到这个......

#define LEDS 48 //I only want ONE mention of this number in the source
int x = LEDS;   //I'm using the value directly too

void DrawFrame()
{
    asm(
    "ldi        R27, 0x00       \n\t"
    "ldi        R26, 0x00       \n\t"
    "ldi        R18, 48         \n\t" //<-- substitution needed here
...
}

So far I have tried all the macro tricks I can think of (#stringification, arg substitution and even #including files with various combinations of values and double quotes and whatnot).

到目前为止,我已经尝试了所有我能想到的宏观技巧(#stringification,arg替换,甚至包含各种值和双引号组合的#including文件等等)。

I'm not at all familiar with the magic of inlining AVR assembly code into AVR Studio's GCC compiler.

我完全不熟悉将AVR汇编代码内联到AVR Studio的GCC编译器中的魔力。

I'm trying to avoid having multiple occurrences of the "48" literal in my source, if the preprocessor can perform this substitution for me that would be great.

我试图避免在我的源代码中多次出现“48”文字,如果预处理器可以为我执行这个替换会很好。

Edit: This is for a microcontroller firmware project - and just to make life interesting, there is almost no spare room for new code to be added.

编辑:这是一个微控制器固件项目 - 只是为了让生活变得有趣,几乎没有空间可以添加新代码。

3 个解决方案

#1


46  

I think it's good to have a stringifying macro in your utils header:

我认为在utils头文件中有一个字符串化的宏是很好的:

#define STR_IMPL_(x) #x      //stringify argument
#define STR(x) STR_IMPL_(x)  //indirection to expand argument macros

Then you can keep the macro numerical and stringify it on the spot:

然后你可以保持宏的数字并在现场将其字符串化:

#define LEDS 48 
int x = LEDS;   

void DrawFrame()
{
    asm(
    "ldi        R27, 0x00       \n\t"
    "ldi        R26, 0x00       \n\t"
    "ldi        R18, "STR(LEDS)"       \n\t"
...
}

The above preprocesses to:

以上预处理:

int x = 48;

void DrawFrame()
{
    asm(
    "ldi        R27, 0x00       \n\t"
    "ldi        R26, 0x00       \n\t"
    "ldi        R18, ""48""       \n\t"
...
}

which relies on the fact that adjacent string literals get concatenated.

这取决于相邻字符串文字被连接的事实。

#2


14  

You can avoid the stringification macro mess if you use a constraint:

如果使用约束,则可以避免字符串化宏乱:

#define LEDS 48

void DrawFrame()
{
    asm volatile(
    "ldi R18, %[leds]"
    : : [leds] "M" (LEDS) : "r18");
}

#3


13  

You need two auxiliary macros for this to work. Then you can take advantage of automatic string concatenation:

您需要两个辅助宏才能工作。然后你可以利用自动字符串连接:

#define STR(x) #x
#define EXPAND(x) STR(x)

#define LEDS 48
int x = LEDS;

void DrawFrame()
{
    asm(
    "ldi        R27, 0x00       \n\t"
    "ldi        R26, 0x00       \n\t"
    "ldi        R18, " EXPAND(LEDS) "       \n\t"
...
}

The reason for using two macros is that the first alone won't expand the parameter passed in.

使用两个宏的原因是第一个单独不会扩展传入的参数。

If you just did this:

如果你这样做:

printf("LEDS = " STR(LEDS) "\n");

It would expand to this:

它会扩展到这个:

printf("LEDS = " "LEDS" "\n");

The EXPAND macro allows the parameter passed in to be substituted as well.

EXPAND宏允许传入的参数也被替换。

So then this:

那么这个:

printf("LEDS = " EXPAND(LEDS) "\n");

Would expand to this:

将扩展到这个:

printf("LEDS = " "48" "\n");

#1


46  

I think it's good to have a stringifying macro in your utils header:

我认为在utils头文件中有一个字符串化的宏是很好的:

#define STR_IMPL_(x) #x      //stringify argument
#define STR(x) STR_IMPL_(x)  //indirection to expand argument macros

Then you can keep the macro numerical and stringify it on the spot:

然后你可以保持宏的数字并在现场将其字符串化:

#define LEDS 48 
int x = LEDS;   

void DrawFrame()
{
    asm(
    "ldi        R27, 0x00       \n\t"
    "ldi        R26, 0x00       \n\t"
    "ldi        R18, "STR(LEDS)"       \n\t"
...
}

The above preprocesses to:

以上预处理:

int x = 48;

void DrawFrame()
{
    asm(
    "ldi        R27, 0x00       \n\t"
    "ldi        R26, 0x00       \n\t"
    "ldi        R18, ""48""       \n\t"
...
}

which relies on the fact that adjacent string literals get concatenated.

这取决于相邻字符串文字被连接的事实。

#2


14  

You can avoid the stringification macro mess if you use a constraint:

如果使用约束,则可以避免字符串化宏乱:

#define LEDS 48

void DrawFrame()
{
    asm volatile(
    "ldi R18, %[leds]"
    : : [leds] "M" (LEDS) : "r18");
}

#3


13  

You need two auxiliary macros for this to work. Then you can take advantage of automatic string concatenation:

您需要两个辅助宏才能工作。然后你可以利用自动字符串连接:

#define STR(x) #x
#define EXPAND(x) STR(x)

#define LEDS 48
int x = LEDS;

void DrawFrame()
{
    asm(
    "ldi        R27, 0x00       \n\t"
    "ldi        R26, 0x00       \n\t"
    "ldi        R18, " EXPAND(LEDS) "       \n\t"
...
}

The reason for using two macros is that the first alone won't expand the parameter passed in.

使用两个宏的原因是第一个单独不会扩展传入的参数。

If you just did this:

如果你这样做:

printf("LEDS = " STR(LEDS) "\n");

It would expand to this:

它会扩展到这个:

printf("LEDS = " "LEDS" "\n");

The EXPAND macro allows the parameter passed in to be substituted as well.

EXPAND宏允许传入的参数也被替换。

So then this:

那么这个:

printf("LEDS = " EXPAND(LEDS) "\n");

Would expand to this:

将扩展到这个:

printf("LEDS = " "48" "\n");