C 宏 - 如何将整数值转换为字符串文字
C Macro - how to get an integer value into a string literal
是否可以将#defined integer 符号的值逐字插入到作为 GCC (AVR Studio) 程序集部分一部分的字符串文字中?
我希望在下面的 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
...
}
但我希望 compiler/assembler(在预处理器完成它的工作之后)看到这个...
#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
...
}
到目前为止,我已经尝试了所有我能想到的宏技巧(#stringification、arg 替换,甚至 #include 具有各种值和双引号组合的文件等等)。
我一点也不熟悉将 AVR 汇编代码内联到 AVR Studio 的 GCC 编译器中的魔力。
我正在努力避免在我的源代码中多次出现“48”文字,如果预处理器可以为我执行此替换,那就太好了。
编辑:这是一个微控制器固件项目 - 只是为了让生活变得有趣,几乎没有多余的空间来添加新代码。
你需要两个辅助宏才能工作。然后你可以利用自动字符串连接:
#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"
...
}
使用两个宏的原因是第一个单独不会扩展传入的参数。
如果您刚刚这样做:
printf("LEDS = " STR(LEDS) "\n");
它将扩展为:
printf("LEDS = " "LEDS" "\n");
EXPAND
宏允许传入的参数也被替换。
那么这个:
printf("LEDS = " EXPAND(LEDS) "\n");
将扩展为:
printf("LEDS = " "48" "\n");
我认为在你的 utils 头文件中有一个字符串化宏是很好的:
#define STR_IMPL_(x) #x //stringify argument
#define STR(x) STR_IMPL_(x) //indirection to expand argument macros
然后你可以保持宏数值并在现场将其字符串化:
#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"
...
}
以上预处理为:
int x = 48;
void DrawFrame()
{
asm(
"ldi R27, 0x00 \n\t"
"ldi R26, 0x00 \n\t"
"ldi R18, ""48"" \n\t"
...
}
这依赖于相邻字符串文字被连接起来这一事实。
如果使用约束,可以避免字符串化宏混乱:
#define LEDS 48
void DrawFrame()
{
asm volatile(
"ldi R18, %[leds]"
: : [leds] "M" (LEDS) : "r18");
}
是否可以将#defined integer 符号的值逐字插入到作为 GCC (AVR Studio) 程序集部分一部分的字符串文字中?
我希望在下面的 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
...
}
但我希望 compiler/assembler(在预处理器完成它的工作之后)看到这个...
#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
...
}
到目前为止,我已经尝试了所有我能想到的宏技巧(#stringification、arg 替换,甚至 #include 具有各种值和双引号组合的文件等等)。
我一点也不熟悉将 AVR 汇编代码内联到 AVR Studio 的 GCC 编译器中的魔力。
我正在努力避免在我的源代码中多次出现“48”文字,如果预处理器可以为我执行此替换,那就太好了。
编辑:这是一个微控制器固件项目 - 只是为了让生活变得有趣,几乎没有多余的空间来添加新代码。
你需要两个辅助宏才能工作。然后你可以利用自动字符串连接:
#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"
...
}
使用两个宏的原因是第一个单独不会扩展传入的参数。
如果您刚刚这样做:
printf("LEDS = " STR(LEDS) "\n");
它将扩展为:
printf("LEDS = " "LEDS" "\n");
EXPAND
宏允许传入的参数也被替换。
那么这个:
printf("LEDS = " EXPAND(LEDS) "\n");
将扩展为:
printf("LEDS = " "48" "\n");
我认为在你的 utils 头文件中有一个字符串化宏是很好的:
#define STR_IMPL_(x) #x //stringify argument
#define STR(x) STR_IMPL_(x) //indirection to expand argument macros
然后你可以保持宏数值并在现场将其字符串化:
#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"
...
}
以上预处理为:
int x = 48;
void DrawFrame()
{
asm(
"ldi R27, 0x00 \n\t"
"ldi R26, 0x00 \n\t"
"ldi R18, ""48"" \n\t"
...
}
这依赖于相邻字符串文字被连接起来这一事实。
如果使用约束,可以避免字符串化宏混乱:
#define LEDS 48
void DrawFrame()
{
asm volatile(
"ldi R18, %[leds]"
: : [leds] "M" (LEDS) : "r18");
}