C 编译器优化不是编译常量?

C 编译器优化不是编译常量?,c,gcc,arm,ld,C,Gcc,Arm,Ld,我在代码中将以下字符串声明为常量。其目的是提供一种在编译输出中存储简单元数据的粗略而简单的方法 const char myString1[] ="abc123\0"; const char myString2[] = {'a','b','c','1','2','3','\0'}; 当我用十六进制编辑器检查输出时,我看到其他字符串常量,但“abc123”没有出现。这使我相信,所启用的优化会导致这些行不被编译,因为它们在程序中从未被引用过 在代码中有没有一种方法可以强制编译此元数据,或者(在代码中

我在代码中将以下字符串声明为常量。其目的是提供一种在编译输出中存储简单元数据的粗略而简单的方法

const char myString1[] ="abc123\0";
const char myString2[] = {'a','b','c','1','2','3','\0'};
当我用十六进制编辑器检查输出时,我看到其他字符串常量,但“abc123”没有出现。这使我相信,所启用的优化会导致这些行不被编译,因为它们在程序中从未被引用过

在代码中有没有一种方法可以强制编译此元数据,或者(在代码中)有没有另一种方法可以将此元数据转换为二进制?我不想对二进制后编译进行任何操作,目标是使其尽可能简单

编译器标志


-O2-g-Wall-c-fmessage length=0-fno内置-ffunction sections-mcpu=cortex-m3-mthumb
使用binutils
strings
命令查看二进制文件中是否存在这些字符串


如果它们已经过优化,那么在声明它们时可以尝试使用
volatile
限定符。请注意,如果它们没有与
volatile
限定符一起使用,一些编译器仍然可以优化它们。

我认为您正在寻找
used
属性:

`过去的

此属性附加到变量,表示变量 必须发出,即使该变量似乎不存在 参考

当应用到C++类模板的静态数据成员时, 属性还意味着如果 类本身被实例化

像这样应用它

__attribute__((used))
const char myString1[] ="abc123\0";
__attribute__((used))
const char myString2[] = {'a','b','c','1','2','3','\0'};

考虑到您发布的编译器标志,它几乎肯定是链接器。
-ffunction sections
标志将每个定义放入对象文件中自己的部分。这使得链接器可以轻松确定数据项或函数未被引用,并从最终二进制文件中省略它。

如果文件范围中有这些变量,编译器必须提供字符串,因为他不知道这些字符串是否将从其他编译单元使用。因此,放置这些变量的任何“.o”文件都必须包含字符串

现在,一个聪明的链接器可以为最终的二进制文件决定不需要这些常量。(尽管我从未观察到)如果你的平台是这样的,你应该在一个“假设”的路径上使用这个变量,事实上程序永远不会采用这个路径。差不多

int main(int argc, char*argv[]){
  switch (argv[0][0]) {
    case 1: return myString1[argv[0][1]];
    case 2: return myString2[argv[0][1]];
  }
  ...
}

我提出了一个解决方案,它使用属性并涉及修改链接脚本

首先,我定义了一个名为“.metadata”的自定义部分

然后,在.ld脚本的
部分
块中,我添加了一个
KEEP(*.metadata))
,这将强制链接器包括
.metadata
,即使它没有被使用

.text :
{
    KEEP(*(.isr_vector))
    KEEP(*(.metadata))
    *(.text*)
    *(.rodata*)

} > MFlash32
注意


我发现
\uuuu attribute\uuuu
关键字必须与变量在同一行,否则它实际上不会显示在二进制文件中,尽管.metadata部分确实显示在内存映射中。

+1,IAR编译器有
\uuu root
,我正在寻找与
gcc
类似的东西。我尝试了“used”和“unused”属性,但都没有成功。我将在GCC文档中进一步查找属性,看看我能想出什么。@BrianV我不太熟悉为arm编译,但听起来好像是链接器在删除数据。也就是说,除非您实际上正在查看对象文件,但没有找到数据。@GeoffReedy您的答复让我走上了正确的道路。看起来ARM工具链有一些特定的属性要做,这正是我想要做的事情。我认为发布正在使用的编译器标志会有所帮助
.text :
{
    KEEP(*(.isr_vector))
    KEEP(*(.metadata))
    *(.text*)
    *(.rodata*)

} > MFlash32