2011-12-16 65 views
0

我試圖初始化C中的一個數組,並且對於每個元素,GCC正在生成一個mov指令(如果有很多元素需要初始化,這是一種低效的方法)。我將如何使用數組數據加載內存並從中返回指針而不是初始化這種方式?初始化C中的數據/數據塊有效

6:array.c  ****   int a[]={1,2,3,4,5,9}; 
26      .loc 1 6 0 
27 0008 C745E001  movl $1, -32(%rbp) 
27  000000 
28 000f C745E402  movl $2, -28(%rbp) 
28  000000 
29 0016 C745E803  movl $3, -24(%rbp) 
29  000000 
30 001d C745EC04  movl $4, -20(%rbp) 
30  000000 
31 0024 C745F005  movl $5, -16(%rbp) 
31  000000 
32 002b C745F409  movl $9, -12(%rbp) 
32  000000 
+3

通過優化編譯。 – Kevin 2011-12-16 17:52:24

+1

嘗試使數組全局。 – 2011-12-16 17:52:38

回答

3

我相信如下回答你的問題:「我將如何裝載存儲器陣列的數據,並從它返回一個指針代替?」:

int a_data[] = {1,2,3,4,5,9}; 

int main() { 
    int *a = a_data; 
} 

這編譯爲:

 .data 
a_data: 
     .long 1 
     .long 2 
     .long 3 
     .long 4 
     .long 5 
     .long 9 

     .text 
main: 
     .cfi_startproc 
     pushq %rbp 
     .cfi_def_cfa_offset 16 
     movq %rsp, %rbp 
     .cfi_offset 6, -16 
     .cfi_def_cfa_register 6 
     movq $a_data, -8(%rbp) 
     leave 
     ret 
     .cfi_endproc 

正如你可以看到,這些值位於數據段中,並且main()只是一個指向數據的指針。

當然,如果你突變a[],這些突變仍然會在那裏,下次你把地址a_data。如果您希望獲得原始值,則應該製作a_data的副本,而不是簡單地使用指向它的指針。

1

我假設a是一個局部變量,對吧?嘗試聲明數組是靜態的 - 那麼它的數據應該從文本塊中加載。然而,變量的含義及其初始化會發生變化。

0

如果a是全局或靜態文件或功能範圍,則數據將存儲在二進制映像中。當應用程序啓動時,系統會將這些值加載到內存中。

int a[]={1,2,3,4,5,9};

static int a[]={1,2,3,4,5,9}; void func(void) { static int a[]={1,2,3,4,5,9}; }

如果是在功能級別非靜態聲明:

void func(void) { static int a[]={1,2,3,4,5,9}; }

的值將不需要被存儲在可執行文件併成爲一系列將存儲立即存儲到內存中(即在堆棧上)。

無論哪種方式,你都無法解決數組初始化時必須將值加載到內存中的事實。

然而,如果該陣列被聲明爲

const int a[] = {1,2,3,5,9}; 

而單元與常量合併編譯,則陣列可以甚至從未存在(取決於文件範圍,並且所有這一點)。

1

根據您的需要你有兩個簡單的選擇:

1)請其靜態

void bar(const int *); 

void foo() { 
    static int a[]={1,2,3,4,5,9}; 

    bar(a); 
} 

收益率 - 這僅僅是靜態數據的參考。

foo: 
.LFB0: 
     .cfi_startproc 
     movl $a.1591, %edi 
     jmp  bar 
     .cfi_endproc 
.LFE0: 
     .size foo, .-foo 
     .data 
     .align 16 
     .type a.1591, @object 
     .size a.1591, 24 
a.1591: 
     .long 1 
     .long 2 
     .long 3 
     .long 4 
     .long 5 
     .long 9 

如果您需要的數據不是靜態或常量,則爲另一種選擇。要有靜態數據,然後自己做一個memcpy將其移動到適當的位置。有趣的是,具有優化的gcc將使用各種策略將其複製到位。

void bar(const int *); 

void foo() { 
    static int s[]={1,2,3,4,5}; 
    int a[sizeof(s)/sizeof(s[0])]; 
    memcpy(a, s, sizeof(s)); 

    bar(a); 
} 

底線,由於用於數據的存儲器位置不固定在編譯時間,因此一些一段代碼需要將數據複製到存儲器中的代碼是必要的。