【问题标题】:variably modified array at file scope in CC中文件范围内的可变修改数组
【发布时间】:2012-11-18 17:11:21
【问题描述】:

我有一些这样的代码:

static int a = 6;
static int b = 3;

static int Hello[a][b] =
{
    { 1,2,3},
    { 1,2,3},
    { 1,2,3},
    { 1,2,3},
    { 1,2,3},
    { 1,2,3}
};

但是当我编译它时,它说错误:

在文件范围内可变地修改“Hello”

这怎么可能发生?我该如何解决?

【问题讨论】:

标签: c arrays static


【解决方案1】:

您不能将静态数组的大小作为变量给出

这就是为什么常量应该是#defined:

#define a 6

这种方式预处理器会将a 替换为6,使其成为有效声明。

【讨论】:

  • 是 a 和 b 定义为 int a = 6; int b = 3 而不是 static int a = 6 有效吗?
  • 不,这仍然是一个变量。使用#define。在 C++ 中有 const 可以让 const int a = 6; 工作,但即使是 const 在 C 中也不够。
  • 宏的替代方法是使用匿名枚举,它们是真正的整数常量enum { a = 6, b = 3, };
【解决方案2】:

简单回答variable modified array at file scope is not possible

详细:

让它编译时integral constant expression,因为数组长度必须在编译时指定。

像这样:

#define a 6
#define b 3

或者,遵循 c99 标准。并像 gcc 一样编译。

gcc -Wall -std=c99 test.c -o test.out

这里的问题是提供长度的可变长度数组可能没有被初始化所以你得到这个错误。

简单

static int a =6;
static int b =3;

void any_func()
{
int Hello [a][b]; // no need of initialization no static array means no file scope.
}

现在使用 for 循环或任何循环来填充数组。

更多信息只是一个演示:

#include <stdio.h>
static int a = 6; 
int main()
{
int Hello[a]={1,2,3,4,5,6}; // see here initialization of array Hello it's in function
                            //scope but still error
return 0;
}


root@Omkant:~/c# clang -std=c99 vararr.c -o vararr
vararr.c:8:11: error: variable-sized object may not be initialized
int Hello[a]={1,2,3,4,5,6};
          ^
1 error generated. 

如果您删除静态并提供初始化,则会产生上述错误。

但如果你保持静态以及初始化,仍然会出错。

但如果你删除初始化并保留static,就会出现以下错误。

error: variable length array declaration not allowed at file scope
static int Hello[a];
           ^     ~
1 error generated.

因此,在文件范围内不允许可变长度数组声明,因此使其成为函数或任何函数内的块范围(但请记住使其成为函数范围必须删除初始化)

注意:由于它被标记为C,因此将ab 设置为const 对您没有帮助,但在C++ const 中可以正常工作。

【讨论】:

  • C99 也不支持文件范围的 VLA。它必须在函数范围或更小。他“可以”在文件范围内使用 const 索引声明,例如包括 static const int a = 10;
  • 它是一个堆栈的东西。如果您的 C99 编译器甚至支持它们,则不强制要求它们;该标准定义了如何它们的行为如果你的C99确实支持它们。这些实现使用堆栈数学来实现它们。您不能在全局(或文件)数据段编译级别这样做。
  • @WhozCraig:但是当我在 main 中定义 a 在这种情况下它也不起作用,使用 -std=c99 编译。现在a 在堆栈上,所以现在有什么问题,我尝试使用gccclang
  • @WhozCraig:我在 SO 本身的某个地方读到,所以发布了答案,但我现在自己面对这个 -std=c99 并且没有编译,有什么线索吗?还要编辑我的答案
  • @WhozCraig:我明白了,你对堆栈的看法是错误的——它可能是全局的
【解决方案3】:

当使用 CLANG/LLVM 时,以下工作:

static const int a = 6;
static const int b = 3;

static int Hello[a][b] =
{
    { 1,2,3},
    { 1,2,3},
    { 1,2,3},
    { 1,2,3},
    { 1,2,3},
    { 1,2,3}
}; 

(要在生成的程序集中看到它,需要使用 Hello,因此不会被优化出来)

但是,如果选择了 C99 模式 (-std=c99),则会产生错误, 如果选择了 -pedantic,它只会生成警告(Wgnu-folding-constant)。

GCC 似乎不允许这样做(const 被解释为只读)

请参阅此线程中的说明:

"Initializer element is not constant" error for no reason in Linux GCC, compiling C

【讨论】:

  • C 中的 'const' 关键字并不真正意味着 'constant'。这会误导一些用户。
  • @Lowpower 我同意 - 这是实现的细节。此外,成本的实际实现似乎有所不同,在 C++ 中,至少一些 const 不再是“只读变量”(意味着符号表中没有指向只读内存段的符号),而是在编译时解析的真正常量。
【解决方案4】:

是的,这很烦人:

const int len = 10;

int stuff[len];

给出错误。我尽量避免使用#define x,因为 const int 是一种更好的声明常量的方法,但是在这些情况下 const int 不是真正的常量,即使编译器完全知道它是。

【讨论】:

    猜你喜欢
    • 2010-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-07
    • 2019-11-16
    相关资源
    最近更新 更多