C 宏的长度是否有限制';什么内容?
对于嵌入式程序,我经常将数据表转换为头定义,头定义被放入.c程序中的变量/数组中 我刚刚编写了一个转换工具,它可能以这种格式产生大量输出,现在我想知道我是否应该意识到这种模式的任何限制 标题示例:C 宏的长度是否有限制';什么内容?,c,macros,preprocessor,C,Macros,Preprocessor,对于嵌入式程序,我经常将数据表转换为头定义,头定义被放入.c程序中的变量/数组中 我刚刚编写了一个转换工具,它可能以这种格式产生大量输出,现在我想知道我是否应该意识到这种模式的任何限制 标题示例: #define BIG_IMAGE_BLOCK \ 0x00, 0x01, 0x02, 0x03, \ 0x04, 0x05, 0x06, 0x07, \ /* this goes on ... */ \ 0xa8, 0xa9, 0xaa, 0xab
#define BIG_IMAGE_BLOCK \
0x00, 0x01, 0x02, 0x03, \
0x04, 0x05, 0x06, 0x07, \
/* this goes on ... */ \
0xa8, 0xa9, 0xaa, 0xab
代码示例(avr gcc):
似乎找不到这个特定问题的答案,似乎被每个人询问的标识符、行长度和宏重新评估限制淹没了。C标准在指定此类限制方面非常宽松。C实现必须能够翻译逻辑源代码行上具有4095个字符的“至少一个程序”(C 2018 5.2.4.1)。但是,在其他线路较短的情况下,它可能会失败。宏替换文本的长度(以字符或预处理器标记度量)未明确寻址 因此,C实现可能对宏替换文本和其他文本的长度有限制,但它不受C标准的控制,而且C实现通常没有很好的文档记录,或者根本没有文档记录
准备源代码中所需的复杂或大量数据的一种常见技术是编写一个单独的程序,在编译时执行,以处理数据并编写所需的源文本。这通常比滥用C预处理器功能更可取。C17第5.2.4.1节第1条列出了一些最低翻译限制。这意味着允许但不要求实现超过这些限制。在下面的引文中,我省略了几个脚注,并强调了一个很可能与这个问题相关的脚注 实现应能够翻译和执行至少一个程序,该程序至少包含 以下每种限制的一个实例: -127块的嵌套级别 -63条件包含的嵌套级别 -12指针、数组和函数声明符(任意组合)修改算术, 结构、联合或 无效的 键入声明 -63完整声明符中括号内声明符的嵌套级别 -63完整表达式中括号表达式的嵌套级别 -内部标识符或宏名称中的63个有效初始字符(每个通用字符名称或扩展源字符被视为单个字符) -外部标识符中的31个有效初始字符(每个指定0000FFFF或以下短标识符的通用字符名视为6个字符,每个指定00010000或以上短标识符的通用字符名视为10个字符,如果y) -一个翻译单元中有4095个外部标识符 -511在一个块中声明块作用域的标识符 -在一个预处理转换单元中同时定义的4095个宏标识符 -一个函数定义中有127个参数 -一个函数调用中有127个参数 -一个宏定义中有127个参数 -一次宏调用中有127个参数 -逻辑源行中的4095个字符 -字符串文字中的4095个字符(串联后) -对象中的65535字节(仅在托管环境中) -包含文件的15个嵌套级别 -1023交换机的机箱标签 语句(不包括任何嵌套 转换 (声明) -单个结构或联合体中的1023个成员 -单个枚举中的1023个枚举常量 -单个结构声明列表中的63层嵌套结构或联合定义 逻辑源行中字符数的相关性是因为宏将扩展为单个逻辑源行。例如,如果在宏定义中使用
\
表示多行宏,则所有部分将拼接为单个源行。这是第5.1.1.2节第1条第ond项目
根据宏的定义方式,它也可能受到其他限制的影响
实际上,所有实现(编译器及其预处理器)都超出了这些限制。例如,gnu编译器允许的逻辑源行长度由可用内存决定。:逻辑行中的4095个字符[或更多]。如果您使用的是Gnu工具集,那么将二进制文件写入文件可能会更容易,然后使用
objcopy
将其转换为ELF对象。
const uint8_t ImageData[] PROGMEM = {
BIG_IMAGE_BLOCK
};