繁体   English   中英

是否可以转发声明 static 数组

[英]Is it possible to forward declare a static array

我需要将 static 数组放入 a.cpp 文件中。 这个数组只用在this.cpp中,所以我想声明它为static。 数组定义挺大的,自然要转发声明。

static int bigIntArray[5000];

/* other code using bitIntArray */

static int bigIntArray[5000] = {
  0x00, 0x9900, 0xffee,
  ...
};

VC 9.0 报错:error C2086: 'int bigIntArray[5000]': redefinition

如果我将“静态”更改为“外部”,问题就会消失,但我不喜欢这种解决方案。

为什么我不能转发声明 static 变量? 这是 C++ 标准要求的吗?

冒着回答一个稍微不同的问题的风险(Charles Bailey 很好地回答了您的问题),您可能希望使用带有 extern 的匿名命名空间。 这可以防止其他翻译单元访问数组变量名称。

namespace {
    extern int bigIntArray[5000];
}

// Code that uses bigIntArray

namespace {
    int bigIntArray[5000] = { ... };
}

这可能会满足您的需求。

如果您使用extern关键字并且不指定初始值设定项,则只能在 C++ 中转发声明对象。 任何其他声明对象的尝试也将是一个定义。 这意味着前向声明的对象将具有外部链接。 不可能向前声明static对象,即具有内部链接的对象。

这与 C 不同,在 C 中,没有初始化程序的任何声明都是临时定义,可以提供后续定义,但它们都必须指定相同的链接。

是否可以转发声明一个静态数组

我认为如果您想使用静态进行声明,则可以使用指针进行转发声明。

指针声明将作为您的前向声明 如果您的/* other code using bitIntArray */是函数定义,只有在您分配内存并初始化它们之后才会调用,您可以以传统方式 bigIntArray[index] 访问元素。

static int *bigIntArray;  // pointer to static integer

/*other code using bitIntArray: function definitions using forward declaration */
int func()
{
        printf("\nfunc %d \n",bigIntArray[3]);
}

int allocate()
{
        bigIntArray = new int[5]{1,2,3,4,5};
}

int main()
{
    allocate();
    func();
    return 0;
}

该数组是静态整数,将仅限于您的编译单元。

警告:人们应该始终根据您的优先事项做出这样的决定。 通过这种方式,您可能会增加代码的可读性或任何其他原因,您想要前向声明,但会以代价。

IMO,正如DA所建议的那样,最好的选择是在定义的命名空间中使用extern。 extern 通知编译器该变量是在别处定义的,并且已定义的命名空间将其作用域仅限于将使用该命名空间的单元。

namespace limited
{
       extern int bigIntArray[];
};
/* other code using bitIntArray */
int func()
{
        using namespace limited;   
        printf("\nfunc %d \n",bigIntArray[3]);
}

namespace limited
{
        int bigIntArray[5] ={1,2,3,4,5};
};

int main()
{
        func();
        return 0;
}

将定义(也是声明)放在前面并取消“前向声明”有什么问题?

static int bigIntArray[5000] = {  0x00, 0x9900, 0xffee,  ...};

/* other code using bitIntArray */

有人说原因是“可读性”。 最初的海报没有提到这是一个动机。

无论如何,我不认为做“奇怪”的事情证明“可读性”是合理的。 我认为创建一个新的文件类型(例如,下面的“*.def”)很奇怪。

定义事物的位置似乎并不重要(至少对我而言)。

最干净,最清晰。 最简单的做法是将定义移到顶部(不要太在意“可读性”)。

其他人说使用“extern”。 问题在于它打开了一个模块之外的对象名称的范围(可能)。


原始发布者也可能没有意识到,在这种情况下,“静态”是一个范围修饰符(而不是存储修饰符。

我遇到了同样的问题,我的解决方案是仅将其转换为一行数字,因为任何格式(空格、换行符等)无论如何都不会使数据可读:

static unsigned char XXX_certificate[1376]={
48,130,5,92,48,176,231,119,149,87,108,108,225,239,138,233,91,116,236,200,117,213,130, <cut>
};

因此我能够将它放在我的源文件的开头,注意它是有效的,因为我不使用自动换行。

您可以仅使用 extern 来转发声明您的数组,如下所示:

extern int bigIntArray[5000];

您还可以删除数组大小

extern int bigIntArray[];

这将告诉编译器该数组是在其他地方(稍后或其他翻译单元)定义的。 在您的情况下,它将稍后在同一个翻译单元中定义,因为它是静态全局的。

在 VC++ 2010 Express 中对我有用。

这是一个未定义的行为。

考虑这个线程以获取更多详细信息:

https://groups.google.com/forum/#!topic/comp.lang.c.moderated/bmiF2xMz51U

来自此链接的报价:

因为 1989 年之前的链接器处理“隐藏”符号的能力各不相同。 如果链接器无法在两个不同的翻译单元中处理两个称为“foo”的符号,这些符号不是同一个对象,那么编译器必须在翻译时(而不是链接时)解决问题。 并且许多 C 编译器都是一次性的,因此当他们第一次看到“foo”时,或者至少第一次引用它时,他们需要为“foo”分配一个地址和空间。 因此限制。

正如基本原理所说的那样:“在 C90 之前,在具有内部链接的前向引用标识符方面的实现差异很大。”

顺便说一句,需要在单个文件中为具有外部链接的符号工作的原因是不完整的版本(“int foo[];”)可能已经在#included 头文件中。

我想你这样做的原因是通过将长常量列表放在代码末尾来提高可读性,对吗? 另一种选择(恕我直言既不好也不坏,只是不同)将使用包含定义的预处理器,例如:

[main file]
#include <iostream>
#include "bigIntArray.def"

int main()
{
    for( int i = 0; i < 10000 ; ++i)
    {
        std::cout << bigIntArray[i] << std::endl;
    }

    std::cin.ignore();
    return 0;
}

[bigIntArray.def]
static int bigIntArray[10000] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ... };

更好的是,在设计方面,将在头文件中声明数组extern ,并将定义放在一个独立的代码文件中......

@DA 答案是最好的。 - 赏金给他
在这方面我同意@Leafy。

想补充一点,如果所有初始值设定项都存在,则实例化中不需要数组大小。

此外, sizeof(bigIntArray)设置数组大小的优势在于能够使用sizeof(bigIntArray)

namespace {
    extern int bigIntArray[5];
}

// Code that uses bigIntArray
void fred() {
  size_t N = sizeof(bigIntArray)/sizeof(bigIntArray[0]);
}

namespace {
    int bigIntArray[/* 5 not needed */] = { 1, 2, 3, 4, 5 };
}

我能想到的最佳解决方案:前向声明一个指向数组的指针,然后定义静态静态数组并将其分配给 EOF 处的指针。

static int *bigIntArray;

/* other code using bitIntArray */

static int _bigIntArray[5000] = {
  0x00, 0x9900, 0xffee,
  ...
};

static int *bigIntArray = _bigIntArray;

This is different from C where any declaration without an initializer is a tentative definition, subsequent definitions can be supplied but they must all specify the same linkage.

很高兴知道,这意味着我们不必在 C 前向声明中明确地放置extern

您可以转发声明引用 static 数组的内联函数,这不会产生额外的运行时成本,因为编译器会将它们优化掉。 这适用于 C 和 C++。

static inline int* bigIntArray();
static inline int bigIntArrayLength();

/* Other code using bigIntArray (through the functions) */

static int big_int_array[/* automatic size */] = {
  0x00, 0x9900, 0xffee,
  ...
};

static inline int* bigIntArray() { return big_int_array; }
static inline int bigIntArrayLength() { return sizeof big_int_array / sizeof int; }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM