嵌套预处理器等同于 #define
Nested preprocessors to equate to a #define
我正在尝试创建一个宏,将 makefile 中的 #define 创建转换为自动生成的 #defines 列表,这些列表是外围组件的起始地址。这是测试代码:
#include <stdio.h>
#include <stdint.h>
/* Created by makefile to specify the core/CPU */
#define CPU_ID 5
/* Autogenerated hardware register descriptors */
#define CPU0_PERIPHERAL_I2C_BASE__ADDR (0x40000)
#define CPU1_PERIPHERAL_I2C_BASE__ADDR (0x56000)
#define CPU2_PERIPHERAL_I2C_BASE__ADDR (0x57000)
#define CPU3_PERIPHERAL_I2C_BASE__ADDR (0x61000)
#define SUBCORE0_PERIPHERAL_I2C_BASE__ADDR (0x67000)
#define SUBCORE1_PERIPHERAL_I2C_BASE__ADDR (0x90000)
#define SUBCORE2_PERIPHERAL_I2C_BASE__ADDR (0xA3000)
#define SUBCORE3_PERIPHERAL_I2C_BASE__ADDR (0xE3000)
#define BASE_ADDR_DEF _PERIPHERAL_I2C_BASE__ADDR
/* defines for translating CPU_ID into autogenerated hardware regs */
#define CPU_ID_0 "CPU0"
#define CPU_ID_1 "CPU1"
#define CPU_ID_2 "CPU2"
#define CPU_ID_3 "CPU3"
#define CPU_ID_4 "SUBCORE0"
#define CPU_ID_5 "SUBCORE1"
#define CPU_ID_6 "SUBCORE2"
#define CPU_ID_7 "SUBCORE3"
#define _JOIN(x,y) x ## y
#define _DEF1(cpu_id) _JOIN(CPU_ID_,cpu_id)
#define _DEF2(cpu_id) _JOIN(_DEF1(cpu_id),BASE_ADDR_DEF)
int main(void)
{
printf("%s\n", _DEF1(CPU_ID)); // <- this prints out "SUBCORE0" which is part of the way there
printf("%X\n", _DEF2(CPU_ID)); // <- This will not compile
return 0;
}
_DEF1 宏在输出中起作用,在这种情况下,如我所料,将是 "SUBCORE1"。我似乎无法让宏再翻译一个级别以将 "SUBCORE1" 与“_PERIPHERAL_I2C_BASE__ADDR” 组合起来创建 "SUBCORE1_PERIPHERAL_I2C_BASE__ADDR" 然后打印出应该为 0x90000 的十六进制值。我是否在扩展过程中遗漏了另一层我没有看到或无法正确处理的宏?
编辑:我知道人们在评论文字字符串,我知道这不是最终目标,但这只是试验过程中的许多迭代步骤之一。我只需要一些例子来展示我正在尝试做的事情。谢谢
- 声明宏不是字符串文字。就像字符串一样。改变前。
"SUBCORE3"
到 SUBCORE3
。预处理器无法删除 "
.
- 您需要使用嵌套宏来触发扩展。前任。
#define _JOIN2(x, y) x ## y
然后 #define _JOIN(x, y) _JOIN2(x, y)
- 所有以下划线开头后跟大字母的标识符都是标准保留的。声明它们是未定义的行为。
#include <stdio.h>
#include <stdint.h>
/* Created by makefile to specify the core/CPU */
#define CPU_ID 5
/* Autogenerated hardware register descriptors */
#define CPU0_PERIPHERAL_I2C_BASE__ADDR (0x40000)
#define CPU1_PERIPHERAL_I2C_BASE__ADDR (0x56000)
#define CPU2_PERIPHERAL_I2C_BASE__ADDR (0x57000)
#define CPU3_PERIPHERAL_I2C_BASE__ADDR (0x61000)
#define SUBCORE0_PERIPHERAL_I2C_BASE__ADDR (0x67000)
#define SUBCORE1_PERIPHERAL_I2C_BASE__ADDR (0x90000)
#define SUBCORE2_PERIPHERAL_I2C_BASE__ADDR (0xA3000)
#define SUBCORE3_PERIPHERAL_I2C_BASE__ADDR (0xE3000)
#define BASE_ADDR_DEF _PERIPHERAL_I2C_BASE__ADDR
/* defines for translating CPU_ID into autogenerated hardware regs */
#define CPU_ID_0 CPU0
#define CPU_ID_1 CPU1
#define CPU_ID_2 CPU2
#define CPU_ID_3 CPU3
#define CPU_ID_4 SUBCORE0
#define CPU_ID_5 SUBCORE1
#define CPU_ID_6 SUBCORE2
#define CPU_ID_7 SUBCORE3
// usually those are called CONCAT or CONCATX or CONCAT2 or XCONCAT etc.
// so I name them the same here
// XCONCAT is a mnemonic from "eXpand then CONCATenate"
#define CONCAT(x,y) x ## y
#define XCONCAT(x,y) CONCAT(x, y)
#define STRING(x) #x
#define XSTRING(x) STRING(x)
// note that glibc defines __CONCAT __XCONCAT __STRING __XSTRING
// trigger the expansions
#define DEF1(cpu_id) XCONCAT(CPU_ID_, cpu_id)
#define DEF2(cpu_id) XCONCAT(DEF1(cpu_id),BASE_ADDR_DEF)
int main(void)
{
printf("%s\n", XSTRING(DEF1(CPU_ID))); // <- this prints out "SUBCORE0", which is at all not part the way here
printf("%X\n", DEF2(CPU_ID)); // <- This will expand to 0x90000
return 0;
}
我正在尝试创建一个宏,将 makefile 中的 #define 创建转换为自动生成的 #defines 列表,这些列表是外围组件的起始地址。这是测试代码:
#include <stdio.h>
#include <stdint.h>
/* Created by makefile to specify the core/CPU */
#define CPU_ID 5
/* Autogenerated hardware register descriptors */
#define CPU0_PERIPHERAL_I2C_BASE__ADDR (0x40000)
#define CPU1_PERIPHERAL_I2C_BASE__ADDR (0x56000)
#define CPU2_PERIPHERAL_I2C_BASE__ADDR (0x57000)
#define CPU3_PERIPHERAL_I2C_BASE__ADDR (0x61000)
#define SUBCORE0_PERIPHERAL_I2C_BASE__ADDR (0x67000)
#define SUBCORE1_PERIPHERAL_I2C_BASE__ADDR (0x90000)
#define SUBCORE2_PERIPHERAL_I2C_BASE__ADDR (0xA3000)
#define SUBCORE3_PERIPHERAL_I2C_BASE__ADDR (0xE3000)
#define BASE_ADDR_DEF _PERIPHERAL_I2C_BASE__ADDR
/* defines for translating CPU_ID into autogenerated hardware regs */
#define CPU_ID_0 "CPU0"
#define CPU_ID_1 "CPU1"
#define CPU_ID_2 "CPU2"
#define CPU_ID_3 "CPU3"
#define CPU_ID_4 "SUBCORE0"
#define CPU_ID_5 "SUBCORE1"
#define CPU_ID_6 "SUBCORE2"
#define CPU_ID_7 "SUBCORE3"
#define _JOIN(x,y) x ## y
#define _DEF1(cpu_id) _JOIN(CPU_ID_,cpu_id)
#define _DEF2(cpu_id) _JOIN(_DEF1(cpu_id),BASE_ADDR_DEF)
int main(void)
{
printf("%s\n", _DEF1(CPU_ID)); // <- this prints out "SUBCORE0" which is part of the way there
printf("%X\n", _DEF2(CPU_ID)); // <- This will not compile
return 0;
}
_DEF1 宏在输出中起作用,在这种情况下,如我所料,将是 "SUBCORE1"。我似乎无法让宏再翻译一个级别以将 "SUBCORE1" 与“_PERIPHERAL_I2C_BASE__ADDR” 组合起来创建 "SUBCORE1_PERIPHERAL_I2C_BASE__ADDR" 然后打印出应该为 0x90000 的十六进制值。我是否在扩展过程中遗漏了另一层我没有看到或无法正确处理的宏?
编辑:我知道人们在评论文字字符串,我知道这不是最终目标,但这只是试验过程中的许多迭代步骤之一。我只需要一些例子来展示我正在尝试做的事情。谢谢
- 声明宏不是字符串文字。就像字符串一样。改变前。
"SUBCORE3"
到SUBCORE3
。预处理器无法删除"
. - 您需要使用嵌套宏来触发扩展。前任。
#define _JOIN2(x, y) x ## y
然后#define _JOIN(x, y) _JOIN2(x, y)
- 所有以下划线开头后跟大字母的标识符都是标准保留的。声明它们是未定义的行为。
#include <stdio.h>
#include <stdint.h>
/* Created by makefile to specify the core/CPU */
#define CPU_ID 5
/* Autogenerated hardware register descriptors */
#define CPU0_PERIPHERAL_I2C_BASE__ADDR (0x40000)
#define CPU1_PERIPHERAL_I2C_BASE__ADDR (0x56000)
#define CPU2_PERIPHERAL_I2C_BASE__ADDR (0x57000)
#define CPU3_PERIPHERAL_I2C_BASE__ADDR (0x61000)
#define SUBCORE0_PERIPHERAL_I2C_BASE__ADDR (0x67000)
#define SUBCORE1_PERIPHERAL_I2C_BASE__ADDR (0x90000)
#define SUBCORE2_PERIPHERAL_I2C_BASE__ADDR (0xA3000)
#define SUBCORE3_PERIPHERAL_I2C_BASE__ADDR (0xE3000)
#define BASE_ADDR_DEF _PERIPHERAL_I2C_BASE__ADDR
/* defines for translating CPU_ID into autogenerated hardware regs */
#define CPU_ID_0 CPU0
#define CPU_ID_1 CPU1
#define CPU_ID_2 CPU2
#define CPU_ID_3 CPU3
#define CPU_ID_4 SUBCORE0
#define CPU_ID_5 SUBCORE1
#define CPU_ID_6 SUBCORE2
#define CPU_ID_7 SUBCORE3
// usually those are called CONCAT or CONCATX or CONCAT2 or XCONCAT etc.
// so I name them the same here
// XCONCAT is a mnemonic from "eXpand then CONCATenate"
#define CONCAT(x,y) x ## y
#define XCONCAT(x,y) CONCAT(x, y)
#define STRING(x) #x
#define XSTRING(x) STRING(x)
// note that glibc defines __CONCAT __XCONCAT __STRING __XSTRING
// trigger the expansions
#define DEF1(cpu_id) XCONCAT(CPU_ID_, cpu_id)
#define DEF2(cpu_id) XCONCAT(DEF1(cpu_id),BASE_ADDR_DEF)
int main(void)
{
printf("%s\n", XSTRING(DEF1(CPU_ID))); // <- this prints out "SUBCORE0", which is at all not part the way here
printf("%X\n", DEF2(CPU_ID)); // <- This will expand to 0x90000
return 0;
}