2016-11-06 6 views
1

から静的に割り当てられた配列を作成するのは、私は2つの静的に割り当てられたグローバルな配列を持っているとしましょう:2つの他のアレイ

const int foo[] = {1, 2, 3}; 
const int bar[] = {4, 5, 6, 7}; 

後、私はまた、静的に割り当てられているされた配列を宣言したいのですが、同じコンパイル単位にfoobarの連結:

const int foo_and_bar[] = ... ? 

可能かどうか?もちろん

、私は

#define FOO_CONTENTS 1, 2, 3 
#define BAR_CONTENTS 4, 5, 6, 7 

const int foo[] = {FOO_CONTENTS}; 
const int bar[] = {BAR_CONTENTS}; 

const int foo_and_bar[] = {FOO_CONTENTS, BAR_CONTENTS}; 

...のようなマクロで醜い何かができる...しかし、私はC言語自体でサポートされているイディオムを探しています。

+0

「本当に醜い」とは何ですか? – Leushenko

+0

おそらく、私はちょうど "醜い"と言うことができました - "本当に醜い"は誇張かもしれません! 「この配列は他の2つの先の宣言された変数の内容を持つ必要があります」という表現ではなく、すべての配列宣言をマクロと宣言に分割する必要があるため、醜いです。マクロを解読してファイルなどで見つけ出す必要があるため、コードを読むのが難しくなります。これらの行に沿って静的に割り当てられたintを配列などに配置する他の多くのシナリオでは、プリプロセッサのサポートは必要ありません。 – BeeOnRope

答えて

1

厳密に言えば、私はあなたが非拡張言語でこれを静的に行うことはできないと思います(GCCのようなコンパイラは、C++のフロントエンドがこの種のものを必要とするという事実を利用して、 。 2つの関連標準の引用符は、鉱山を強調:初期化子で

すべての式を定数式または文字列リテラルでなければなら静的またはスレッド記憶域期間を持つオブジェクトのために。

6.7.9 p4

アレイ添字[]とメンバアクセス.->オペレータ、アドレス&及び間接*単項演算子、およびポインタキャストはの作成に使用することができますアドレス定数はですが、これらの演算子を使用してオブジェクトの値にアクセスしてはなりません。

6.6 p9)つまり

、ファイルスコープで[]オペレータのためのいくつかの合法的な用途がありますが、あなたは明示的にその時点で、配列の内容を読み取ることが許可されていません。したがって、単純にイニシャライザ(マクロソリューションと同じ機械的なもの)を複製することなく、1つの配列の内容を別のものの内容と同じにするには、実行時に実行する必要があります。ここで

+0

私は "あなたができる!"これは「あなたができない」のように決定的に似ています。 – BeeOnRope

-2
Yup! you can create another array whose size is the sum of both foo and bar . Then you can one by one copy the elements using looping statements. first loop will begin from 0 to the size of first array and second loop will begin from the size of first array to the size of the second array. 
1

別のアプローチである:すべての3つの配列は読み取り専用されているので


、あなたにもいずれか一方のみを割り当てることができる:

const int foo_and_bar[] = {1,2,3,4,5,6,7}; 

その後、各サブアレイのインデックスとサイズを示す追加の変数を使用します。

int fooIndex = 0, fooSize = 3; 
int barIndex = 3, barSize = 4; 
+0

それはユースケースに応じて妥当でしょう。配列を必要とする場所で配列を使用する必要があり、動作を変更できない場合は動作しません。静的配列でできることは、 'sizeof(array)'のようにポインタだけではできないものもあります。 – BeeOnRope

+0

@BeeOnRope:「行動を変更する」とはどういう意味ですか? –

+0

私は、コードを変更することができない限り、私はできないでしょう、ポインタとサイズ(または配列、オフセットとサイズ)ではなく、完全な配列を期待して、必然的に可能であるかまたは望ましい。 – BeeOnRope

1

問題は、すべての静的記憶域持続時間変数が、言語によって定義されたコンパイル時定数である必要があるイニシャライザリストで機能することです。別の変数は、たとえconstとして宣言されていても、コンパイル時定数とはみなされません。また、別の配列から配列を初期化したり、直接割り当てることはできません。

言語の制限があるため、これを行うことはできません。実際には、イニシャライザーリスト用の#definesのバージョンがこれに対する共通の解決策です。それは簡単な解決策なので、最も良い解決策です。


あなたはさまざまな方法でデータにアクセスする方法を探している場合は、一つの代替は、労働組合とC11匿名の構造を持つものになることができます:あなたがのハードコピーをしたい場合は今

#include <stdio.h> 

#define FOO_INIT 1, 2, 3 
#define BAR_INIT 4, 5, 6, 7 

#define FOO_SIZE (sizeof((int[]){ FOO_INIT })/sizeof(int)) 
#define BAR_SIZE (sizeof((int[]){ BAR_INIT })/sizeof(int)) 

typedef union 
{ 
    int array [FOO_SIZE + BAR_SIZE]; 
    struct 
    { 
    int foo [FOO_SIZE]; 
    int bar [BAR_SIZE]; 
    }; 
} foobar_t; 



int main (void) 
{ 
    static const foobar_t foobar = { .foo = {FOO_INIT}, .bar = {BAR_INIT} }; 

    // print 1 2 3 4 5 6 7 
    for(size_t i=0; i<FOO_SIZE + BAR_SIZE; i++) 
    { 
    printf("%d ", foobar.array[i]); 
    } 
} 

配列、あなたは実際にfoobar_t foobar2 = foobar;を行うことができます。配列の代入は許可されていませんが、配列を含む構造体/共用体の代入では問題ありません。 (ただし、foobar2に静的な記憶期間がある場合はまだ動作しません)