0

I was trying to initialize an array in C and for each element GCC is generating a mov instruction(which is an inefficient approach if there are many elements to be initialized). How will I load memory with array data and return a pointer from it instead of initializing this way ?

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
10
  • 3
    Compile it with optimization. Commented Dec 16, 2011 at 17:52
  • 2
    granted, I'm not too familiar with assembly, but what would be the optimal approach, assuming it has to be initialized at runtime? Commented Dec 16, 2011 at 17:52
  • @Bwmat. that would be copied array. you initialize empty array in function and copy contents from external array to it. fastest initialized at runtime array. Commented Dec 16, 2011 at 18:18
  • 1
    @fazo: Are you sure that's faster? I don't know low-level stuff, but I would have guessed otherwise. moves takes more instructions in code, but doesn't require a read from other memory, nor a loop. Commented Dec 16, 2011 at 18:34
  • 1
    @alertjean, just declaring your array const should have sufficed, I think. gcc is quite good then to optimize stores that are not necessary. If on the other hand you'd want to be that array modifiable, you'd have to store the value at some point. Commented Dec 16, 2011 at 20:07

4 Answers 4

3

I believe the following answers your question "How will I load memory with array data and return a pointer from it instead?":

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

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

This compiles to:

        .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

As you can see, the values live on the data segment, and main() simply takes a pointer to the data.

Of course, if you mutate a[], these mutations will still be there next time you take the address of a_data. If you expect to get the original values, you should be making a copy of a_data, not simply using a pointer to it.

Sign up to request clarification or add additional context in comments.

3 Comments

Better have a_data with a const qualified type, I think
@JensGustedt: That depends on what the OP wants to do with it.
If it is acceptable to use static data, I don't see why you'd have to have a second variable. Just name the static variable a and you are done.
1

I assume that a is a local variable, right? Try declaring the array static - then its data should get loaded from a text block. The meaning of the variable and its initialization is going to change, however.

Comments

1

Depending on your needs you have two simple choices:

1) Make it static

void bar(const int *);

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

    bar(a);
}

Yields - which is just a reference to the static data.

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

The other choice if you need data that is not static or constant. Is to have the static data around then do a memcpy yourself to move it into the appropriate places. What's interesting is that gcc with optimization will then use a variety to strategies to copy it into place.

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

Bottom line, the code is necessary since the memory location for the data is not fixed at compilation time and thus some piece of code needs to copy the data into the memory.

Comments

0

If a is a global or a static file or function scope the data is going to be stored in the binary image. When the application starts up the run time system is going to load the values into memory.

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

if a is declared at the function level non-static:

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

The the values won't need to be stored in the executable and be a series of storing immediates into memory (i.e. on the stack).

Either way you can't get around the fact the values have to be loaded into memory when the array is initialized.

However if the array is declared as

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

And the unit is compiled with constant folding then the array may never even exist (depending upon file scope and all that).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.