0

私はビジュアル C++ 2010 を使用しています。この質問は長い間私を混乱させました。*.cpp で suan 配列を定義できます。

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は、ヘッダー ファイルで配列の長さを明示的に宣言する必要があります。それ以外の場合、コンパイラは単にその情報にアクセスできません。コンパイラが読み取らない定義オブジェクトファイルに埋め込まれています。

あなたが望むことをすることができるかもしれない他の2つの方法があります:

  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宣言のみが表示され、配列サイズについては言及されていません。

考えられる回避策の 1 つは、サイズを保持する別の変数を追加することです。ヘッダ:

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 に答える
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 に答える