0

我正在使用visual C++ 2010。这个问题让我困惑了很长时间。我可以在 *.cpp 中定义一个数组:

wstring pairs[][2] =
    {
        {L"\\ben\\b",               L"English"},
        {L"\\bfr\\b",               L"French"},
        {L"\\bit\\b",               L"Italian"},
        {L"\\bde\\b",               L"German"},
        {L"\\bes\\b",               L"Spanish"},
        {L"\\bpl\\b",               L"Polish"},
        {L"\\bru\\b",               L"Russian"},
        {L"\\bzh_cn\\b",            L"ChinesePRC"},
        {L"\\bzh_tw\\b",            L"ChineseTaiwan"},
        {L"\\bja\\b",               L"Japanese"},
        {L"\\bko\\b",               L"Korean"},
        {L"\\bpt\\b",               L"PortugueseStandard"},
        {L"\\btr\\b",               L"Turkish"},
        {L"\\bnl\\b",               L"Dutch"},
        {L"\\blt\\b",               L"Lithuanian"},
        {L"\\blv\\b",               L"Latvian"},
        {L"\\bet\\b",               L"Estonian"}
    };

并像这样在 *.h 中声明数组:

extern wstring pairs[][2];

现在我可以在其他 *.cpp 中使用该数组,但我无法获得pairs使用代码的大小:

size_t cnt = _countof(pairs);

我收到错误消息:

1>e:\work\vc++\justtest\console\console.cpp(45): error C2893: Failed to specialize function template 'char (*__countof_helper(_CountofType (&)[_SizeOfArray]))[_SizeOfArray]'
1>          With the following template arguments:
1>          'std::wstring [2]'

我很困惑是否可以像这样使用数组?有人可以帮助我吗?

4

5 回答 5

4

如果要获取extern数组的长度,必须在头文件中显式声明数组的长度。否则,编译器根本无法访问该信息;它隐藏在定义的目标文件中,编译器不会读取该文件。

您可以通过其他两种方式来做您想做的事:

  1. 您可以为数组的长度创建另一个变量。然后也extern为此做一个,您将能够访问另一个文件中的长度。

    缺点:长度仍然不会静态知道。但是,如果您进行了链接时优化(不太可能)并且没有将该值用于任何花哨的元编程,那可能不是问题。

  2. 您可以在标记数组末尾的末尾添加一个标记值。

    缺点:使用这种方法也不会静态知道长度。此外,每次您想要数组的长度时,都是 O(n) 操作。如果您只遍历数组,这可能不是问题。

于 2012-12-26T02:17:25.683 回答
3

您可以使用带有 的数组extern,但您要么 (1) 需要显式声明大小,要么 (2) 在字符串中放置一个类似于 null 终止符的终止符条目,以计算运行时的条目数。

解决方案1:

extern wstring pairs[17][2];

通过此更改,sizeof(pairs)将正确定义。

解决方案2:

wstring pairs[][2] =
{
    {L"\\ben\\b",               L"English"},
    {L"\\bfr\\b",               L"French"},
    ...
    {L"\\blv\\b",               L"Latvian"},
    {L"\\bet\\b",               L"Estonian"}, {0, 0}
};

现在您可以运行一个快速循环pairs以到达*pairs[i] == 0,这将指示最后一个条目。

于 2012-12-26T02:17:40.887 回答
2

它看起来像是_countof一个模板函数,需要在编译时知道数组大小。而且在编译时,只有你的extern声明是可见的,它没有提到数组大小。

一种可能的解决方法是添加另一个变量来保存大小。标题:

extern wstring pairs[][2];
extern const size_t pairs_size;

来源:

wstring pairs[][2] = { /*...*/ };
const size_t pairs_size = _countof(pairs);

或者,正如其他人建议的那样,使用哨兵在运行时确定数组大小。

或者,如果使用允许,切换到一个std::vector或其他容器。(这可能会弄乱静态初始化器的顺序。)

于 2012-12-26T02:24:51.190 回答
1

将 a 添加{ NULL, NULL }到数组的末尾。然后使用类似这样的循环:

extern wstring pairs[][2];
...
int do_stuff()
{
    for(int i = 0; pairs[i][0] != NULL; i++)
    {
      ... do things with pairs as you like ... 
    }
}

希望这就是你要找的。

于 2012-12-26T02:18:53.573 回答
0

接近但没有奖牌。这是大多数现代编译器都应该使用的东西。在声明数组的源文件中,执行以下操作:

const unsigned int amrd_count=sizeof( amrd ) /sizeof( amrd[0] );

在您的标题中,插入如下内容:

extern T amrd[];
extern const unsigned int amrd_count;

对我来说,这适用于 XCode (Apple LLVM 版本 9.0.0 (clang-900.0.39.2)) 和 gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-16)

于 2017-12-18T11:56:48.557 回答