c - 为什么 const 局部数组/结构在 c 中不是静态的?

标签 c embedded

我正在为嵌入式系统编程,其中闪存存储空间和 RAM 使用都是一个问题。

根据 c11 标准第 6.2.4 节:

An object whose identifier is declared with no linkage and without the storage-class specifier static has automatic storage duration ... The initial value of the object is indeterminate. If an initialization is specified for the object, it is performed each time the declaration or compound literal is reached in the execution of the block

如果我理解正确的话,这意味着函数如下:

static void func(void){
   const struct MyStruct j={5,6,7,8};
   const char k[]="long string of some sort";
   /*...some code...*/
}

jk 需要在进入函数时(重新)初始化,这意味着 j 和 k 的存储位置都必须放在 RAM 中并使用 memcpy 之类的东西从 FLASH 中的数据部分进行初始化。这意味着它同时使用 RAM 和闪存中的资源。与类似的东西相比:

static void func(void){
   static const struct MyStruct j={5,6,7,8};
   static const char k[]="long string of some sort";
   /*...some code...*/
}

现在 jk 仅初始化一次,可以直接从 FLASH 引用,而无需复制到 RAM。

不将(大于寄存器大小)const声明为static有什么好处吗?

基本上,我想知道我是否应该始终将我的 const 声明为 static 或者是否有理由不这样做。

最佳答案

我用它做了一些实验,这是代码:

extern void other_call (int);
extern void other_call2 (const char *);

void test ()
{
    const int var = 32;
    const char * const var2 = "this is a string";
    int var3;

    other_call (var);
    var3 = var * 10;
    other_call2 (var2);
    other_call (var3);
}

然后我用以下方法构建它:

arm-none-eabi-gcc -std=gnu99 -O0 -fno-common -g3 -Wall -c -fmessage-length=0 -fno-builtin -ffunction-sections -fdata-sections "-Wa,-adhln=test.s" -mcpu=cortex-m0 -mthumb -specs=redlib.specs -MMD -MP "../src/test.c"

并在 const 初始化中获取此程序集:

  42 0004 00AF          add r7, sp, #0
   6:../src/test.c ****     const int var = 32;
  44                    .loc 1 6 0
  45 0006 2023          movs    r3, #32
  46 0008 FB60          str r3, [r7, #12]
   7:../src/test.c ****     const char * var2 = "this is a string";
  47                    .loc 1 7 0
  48 000a 0C4B          ldr r3, .L2
  49 000c BB60          str r3, [r7, #8]

编译器将 const 值 32 加载到 R3,然后将其存储在 RAM 中的 STACK 中(R7 加载了 SP)。 对于字符串 var2 ,编译器将执行与常量数字相同的操作,不同之处在于它将使用 .L2,它是字符串地址的占位符。

请注意,它确实将变量写入了 STACK,但没有必要,因为它们是 const 并且不会更改。

现在使用 `-O3 启用优化:

   6:../src/test.c ****     const int var = 32;
   7:../src/test.c ****     const char * var2 = "this is a string";
   8:../src/test.c ****     int var3;
   9:../src/test.c **** 
  10:../src/test.c ****     other_call (var);
  37                    .loc 1 10 0
  38 0002 2020          movs    r0, #32
  39 0004 FFF7FEFF      bl  other_call
  40                .LVL1:
  11:../src/test.c ****     var3 = var * 10;
  12:../src/test.c ****     other_call2 (var2);
  41                    .loc 1 12 0
  42 0008 0348          ldr r0, .L2
  43 000a FFF7FEFF      bl  other_call2

请注意,不涉及 STACK 操作。它将常量直接加载到寄存器并跳转到使用它们的函数。甚至 var3 也被优化掉了。

让我们看看没有 const 限定符会发生什么?好吧,我不需要发布任何程序集,因为它没有什么不同。在建议的代码中,const 限定符不会对生成的程序集产生任何更改。即使在优化 -O0 编译器仍然会为 const 变量分配 STACK。如果您确实想强制编译器避免堆栈,请启用优化。我还使用 #define 而不是 const 进行了测试,它仍然使用 -O0 上的 STACK。

现在,将变量静态,编译器做了它应该做的事情,它将变量存储在RAM中,并在使用前将其加载到寄存器中,但不在-O3<中。启用优化后,编译器会简单地忽略示例中的static。考虑到变量只被读取而从未被写入,这种优化是正确的。

我知道这是单个编译器的单一情况,但它代表了大多数情况,一定存在 const 可能会产生我不知道的差异的极端情况,但是,对于函数内部的变量,如果您想优化,请使用标志,而不是 conststatic

关于c - 为什么 const 局部数组/结构在 c 中不是静态的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42700321/

相关文章:

c - 即使我初始化了所有内容,我也无法弄清楚这个段错误。几乎相同的代码在另一个程序中运行良好。

io - select() 没有响应写入/dev/input/mice

Contiki时钟时间模块不更新

C - 确定所有偶数位是否都设置为 1

c - 在结构中匹配和搜索并标记 true 或 false C

embedded - 充分利用糟糕的 "checksum"算法

encryption - 世界上哪里需要收银机中的加密软件,在这种情况下需要什么安全措施?

c - 使用 Google Test 测试 C 函数

c - 在嵌入式系统上使用 fopen() 需要什么?

c - 编写一个make文件来编译一个项目,该项目的源代码和头文件位于不同的目录中