【问题标题】:c - Declaring a variable with both register and static storage classesc - 使用寄存器和静态存储类声明变量
【发布时间】:2016-01-09 14:57:01
【问题描述】:

(ANSI-C 89) 您好,是否可以同时声明 staticregister 变量?每当我尝试这样做时,我都会得到一个错误消息:multiple storage classes in declaration specifiers

这是代码:

#include <stdio.h>

void f1(static int i);
int main()
{
    static register int i;

    i = 5;
    f1(i);
}

void f1(static int i)
{
    static int y =6;
    y+=1;
    printf("\n Y=%d \n",y);
}

还有

【问题讨论】:

  • 你为什么要这样做?
  • 你无法做到这一点,因为static 变量存储在 .bss 区域中,而register 存储在高速 CPU 寄存器中。
  • @stackptr:我不认为这符合 C 标准。
  • @KerrekSB 是什么意思?仅仅因为 C 标准没有说明静态变量的存储位置,并不意味着大多数编译器不会在 .bss 区域中分配静态变量。
  • @stackptr:当然,但这与这个问题完全无关。 “大多数编译器所做的”并不是为什么不允许 OP 做她想做的事情的理由。

标签: c gcc static c89 register-allocation


【解决方案1】:

registerstatic都是存储类说明符,最多可以指定一个存储类说明符。

来自 C11 标准 ISO/IEC 9899:2011:

6.7.1 存储类说明符

语法

  1.      存储类说明符:
    typedef
    extern
    static
    _Thread_local
    auto
    register

约束

  1. 在声明的声明说明符中最多可以给出一个存储类说明符,除了_Thread_local 可能与staticextern 一起出现。120)

120)参见“未来语言方向”(6.11.5)。

【讨论】:

    【解决方案2】:

    C 中的每个对象都有一个存储持续时间,这正是以下之一:自动、静态、已分配和(从 C11 开始)线程本地。

    除了分配的存储之外,对象的存储持续时间由引用该对象的声明名称的链接决定。 (分配存储的对象没有与它们关联的任何名。)标识符的链接由声明中出现的存储类说明符确定。由于一个对象只能有一种类型的链接和一种存储持续时间,因此 C 语言只允许您指定一个存储类说明符(C11 中的 _Thread_local 除外)。

    链接和结果存储时间如下:

    • static:内部联动,静态存储时长
    • extern:外部联动,静态存储时长
    • auto,register:无联动,自动存储时长。只允许在块范围内。
    • none:块作用域与auto相同,文件作用域与extern相同。

    如您所见,几乎任何两个存储类说明符都会导致不同的、不兼容的语义。因此,该语言简单地禁止使用多个存储类说明符,因为对于大多数组合,并不清楚请求了哪种行为。似乎autoregister 是仅有的两个可以一起应用的说明符。 C11实际上添加了_Thread_local可能与externstatic同时出现的异常,导致后者与线程本地存储时长联动。

    不同的存储持续时间和链接可能需要不同的实现。由于没有链接的变量需要在每个范围内都是唯一的,因此它们通常会放在函数调用堆栈上(如果需要存储它们)。相比之下,具有静态存储持续时间的变量需要在整个程序期间持续存在,因此不能放在调用堆栈上,而是需要进入整个可用的内存的其他部分。

    【讨论】:

      【解决方案3】:

      您将无法做到这一点,因为静态变量存储在.bss 内存区域中,而寄存器存储在高速 CPU 寄存器中。

      https://en.wikipedia.org/wiki/.bss

      【讨论】:

      • 为什么有这么多反对票?这是所有人的最佳答案。
      • 问题是关于标准 C(准确地说是 C89)。没有 C 标准规定存在.bss 内存区域;正如两个被赞成的描述所解释的那样,它根据存储持续时间定义了编译器的行为。这个答案没有帮助,因为它涉及一种特定的实现,而不是语言标准的要求。
      • trentcl 说得对。这是可恶的“全世界都是英特尔”的说法。
      • .bss,即使它在 C 标准中不存在,几乎每个实现都有一个 .bss 部分。但是register-变量也不能存储在物理寄存器中。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-01
      相关资源
      最近更新 更多