2011-12-16 8 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

+1

配列をグローバルにしてみてください。 –

+2

、私はアセンブリに慣れていませんが、実行時に初期化する必要があると仮定して、最適なアプローチは何ですか? – Bwmat

答えて

3

私は次のことがあなたの質問に答えると信じて「私は配列データをメモリにロードし、代わりにそれからポインタを返しますどのように?」:あなたのよう

 .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 

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

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

これはにコンパイル値はデータセグメントに存在し、main()は単にデータへのポインタを取ります。

もちろん、a[]を突然変異させると、これらの突然変異は次回にa_dataというアドレスを使用してもそこに残ります。元の値を取得する予定の場合は、ポインタを単に使用するのではなく、a_dataのコピーを作成する必要があります。

+0

'const'修飾型の' a_data'を持っているほうがいいと思っています。 –

+0

@JensGustedt:それはOPが何をしたいのかによって決まります。 –

+0

'static 'データを使用することが許容されるなら、なぜ2番目の変数を持たなければならないのかわかりません。 'static'変数に' a'という名前をつければ完了です。 –

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)

void bar(const int *); 

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

    bar(a); 
} 

利回りそれは、静的行います

1

は、ニーズに応じて、次の2つの単純な選択肢があります。

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 

静的でも定数でもないデータが必要な場合は、もう1つ選択します。その周りの静的なデータを持って、あなた自身が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); 
} 

ボトムラインデータのメモリ位置がコンパイル時に固定され、従って、コードのいくつかの部分は、メモリにデータをコピーする必要がないので、コードが必要です。