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