Инициализируйте массив / блок данных в C эффективно - PullRequest
0 голосов
/ 16 декабря 2011

Я пытался инициализировать массив в C, и для каждого элемента GCC генерирует инструкцию mov (что является неэффективным подходом, если нужно инициализировать много элементов). Как я буду загружать память данными массива и возвращать указатель из нее вместо инициализации таким образом?

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

Ответы [ 4 ]

3 голосов
/ 16 декабря 2011

Я полагаю, что следующие ответы на ваш вопрос «Как я буду загружать память данными массива и вместо этого возвращать из нее указатель?»:

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 голос
/ 16 декабря 2011

В зависимости от ваших потребностей у вас есть два простых варианта:

1) Сделать статичным

void bar(const int *);

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

    bar(a);
}

Yields - это просто ссылка на статические данные.

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);
}

Суть в том, что код необходим, поскольку область памяти для данных не фиксируется во время компиляции, и, следовательно, некоторый фрагмент кода должен копировать данные в память.

1 голос
/ 16 декабря 2011

Я предполагаю, что a является локальной переменной, верно?Попробуйте объявить массив статическим - тогда его данные должны загружаться из текстового блока.Однако значение переменной и ее инициализация изменятся.

0 голосов
/ 16 декабря 2011

Если 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}; }

если a объявлено на нестатическом уровне функции:

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

Значения не нужно хранить в исполняемом файле и представлять собой серию непосредственных сохранений в памяти (то есть в стеке).

В любом случае вы не можете обойти тот факт, что значения должны быть загружены в память при инициализации массива.

Однако, если массив объявлен как

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

И модуль компилируется с постоянным сворачиванием, тогда массив может даже не существовать (в зависимости от области файла и всего этого).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...