Home > database >  Question about how arrays stored in memory
Question about how arrays stored in memory

Time:10-22

I'm a beginner in c language and programming, I heard that an array's elements were stored in successive memory location.

  1. if I somehow manage to make memory location like this:memory drawing what will happen if I declare an int8_t arr[2], will it go wrong?
  2. does compiler have a list of the allocated memory and check when it declares variable?
  3. calling malloc(1) in a while loop, why their return value has the difference of 0x20?

thanks for your helping!

CodePudding user response:

I'm a beginner in c language and programming, I heard that an array's elements were stored in successive memory locations.

How the memory allocation process works is left to the implementation. Every compiler, hardware port or version may do this completely different way. So you can't assume that the arrays will be placed in the successive memory location.

But the array is a continuous chunk of memory and elements are stored one after another so you can use element type pointer arithmetic to calculate references.

if I somehow manage to stuff values in every 8-bit location (like buttons on the flute, sorry for my broken English). what will happen if I declare an int arr[2], will it go wrong?

I do not understand what you mean, but if you want to store 8 bits of data use the array of int8_t. Use the correct type for the job. int8_t array[2] and you will have an array of the two 8 bits integer numbers.

how the compiler knows which location is allocated?

I think it is much too early for you to think about the compiler design. At the moment simply assume that it happens magically behind the scenes.

calling malloc(1) in a while loop, why their return value has the difference of 0x20?

Because it is how your malloc function works. Another implementation may work a completely different way and some will return addresses not related to the previous one.

will the irrelevant part of my code executed at the same time to save the time?

The code will be executed exactly as you wrote it, but if you do not have processes/tasks nothing in your code will execute in parallel.

CodePudding user response:

Given the declaration

int a[5];

you get something like this in memory (each square represents an int object):

    --- 
a: |   | a[0]
    --- 
   |   | a[1]
    --- 
   |   | a[2]
    --- 
   |   | a[3]
    --- 
   |   | a[4]
    --- 

That's it - no other metadata regarding size or type or starting address is stored as part of the array. All you get is a contiguous sequence of objects of the specified type. There is no object a that's separate from the array elements themselves.

what will happen if I declare an int8_t arr[2], will it go wrong?

Not sure what you mean. Declarations are not processed at runtime; during translation, the compiler analyzes the code and generates the machine code necessary to set aside any storage at program or function entry.

does compiler have a list of the allocated memory and check when it declares variable?

During translation, the compiler will keep track of declarations (using what's often called a symbol table) and will issue any diagnostics if the declaration isn't valid (incomplete type, no size, syntax error, whatever). No such checks are done at runtime.

calling malloc(1) in a while loop, why their return value has the difference of 0x20?

Because unless you're also calling free() on the memory you allocated, you're allocating a new block of memory every time through the loop, each of which starts at a different address.

Depending on the implementation, malloc may allocate more memory than necessary for the given object to store bookkeeping information about that object. After all, when you call free, all you give it is the starting address of the memory you allocated - you don't tell it how much memory to free. That information has to be stored somewhere, and many implementations set aside some extra space prior to the allocated block to do so:

 ---  --- 
|   |    | 
 ---     |
 ...      ---- bookkeeping data
 ---     |
|   |    |
 ---  --- 
|   |    | <--- this byte's address returned by malloc
 ---     |
|   |    |
 ---      ---- Requested block
 ...     |
 ---     | 
|   |    |
 ---  --- 

CodePudding user response:

  1. An array is a collection of a data type stored in memory. When you declare an array like:
int arr[2];

Your compiler allocates 2 * sizeof(int) amount of memory in RAM and the pointer to the beginning of that memory is used when arr is referenced. I don't know what could go wrong or what you mean by "will it go wrong?"

  1. Compiler knows the location of the allocated array because compiler is the one to allocate it in the first place. The place is already (mostly) determined by the compiler.

  2. Calling malloc in a while loop is different from declaring an array such as int arr[2]. malloc is a function which allocates some space on the heap. Heap is a special memory allocated for the dynamic use in a program. The space for heap is provided by the OS and this space is divided into smaller chunks by the implementation of malloc. The reason that there is 0x20 difference between the addresses that there may be a heap entry for each malloc you do. For example think of a heap entry such as:

0x1000 : 4 Bytes stores the size of the data inside the entry
0x1004 : 8 Bytes stores a pointer to the next entry 
0x100C : 8 Bytes some other data that maybe used in heap entry
0x1014 : 4 Bytes the integer itself
0x1018 : The start of the next entry etc.
  1. I do not know what that means.

Edit: For all those who say that arrays are not pointers. Consider the following code:

int someArrFunc()
{
    int arr[2];
    int *ptr = arr;

    arr[0] = 451;
    *ptr = 885;

    arr[1] = 452;
    *  ptr = 886;

    int abc = sizeof(arr);
}

If we compiled this code the disassembly would be:

someArrFunc():
        push    rbp
        mov     rbp, rsp

        lea     rax, [rbp-20]
        mov     QWORD PTR [rbp-8], rax

        mov     DWORD PTR [rbp-20], 451

        mov     rax, QWORD PTR [rbp-8]
        mov     DWORD PTR [rax], 885

        mov     DWORD PTR [rbp-16], 452

        add     QWORD PTR [rbp-8], 4
        mov     rax, QWORD PTR [rbp-8]
        mov     DWORD PTR [rax], 886

        mov     DWORD PTR [rbp-12], 8

        nop
        pop     rbp
        ret

Here rbp-20 is the start address of the arr and rbp-8 is adress of ptr value. You can observe from the code that there is no difference between setting the arr and ptr in terms of memory. The variable arr in this case refers to rbp-20 while the pointer's value is also rbp-20. The only real difference between them is that the pointer holds extra memory since we are able to change its value.

I see that there is a decay but it is not relevant to my explanation of the memory structure. Moreover see that sizeof isn't stored in memory. It is an immediate value that is placed by the compiler with prior knowledge of its size.

  • Related