2016-11-06 103 views
1
靜態分配的數組

比方說,我有兩個靜態分配的全局數組:創建其他兩個數組

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

也許我剛纔說過「醜陋」 - 「真醜」可能是誇張!這很醜陋,因爲每個數組聲明都需要分解成一個宏和聲明,而不是僅僅表示「這個數組應該包含這兩個先前聲明的變量的內容」。讀取代碼更加困難,因爲您需要破譯宏並在文件中找到它等等。當然,沿着這些行(將靜態分配的int放入數組等等)的許多其他場景不需要預處理器支持。 – BeeOnRope

回答

1

嚴格地說,我認爲你可以用未延伸的語言靜態地做到這一點(我確信像GCC這樣的寬容編譯器允許在這裏有幾個選項,儘管它們的C++前端需要這樣的事實) 。兩個相關的標準報價,強調字體雷:

所有在初始化表達式有靜態或線程存儲期限爲常量表達式或字符串文字的對象。

6.7.9 p4

陣列-標[]和成員訪問.->運營商而言,地址&和間接*一元運算符,並且指針類型轉換可以在創建一個的使用地址常量,但不應使用這些運算符訪問對象的值。

6.6 p9

換句話說,同時有在文件範圍內的[]操作一些合法的用途,您明確不允許在那個時間閱讀數組的內容。因此,要將一個數組的內容設置爲與另一個數組的內容相同,而不是簡單地複製初始化器(這在機械上是宏解決方案的作用),則必須在運行時執行一定量的工作。

+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

這是一種替代方法:


由於所有三個數組是隻讀的,你可能也只分配其中之一:

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;。 C非常奇怪,因爲雖然它不允許分配數組,但對於包含數組的結構/聯合的賦值完全沒問題。 (但如果foobar2具有靜態存儲時間,那麼這仍然不起作用。)

相關問題