I'm a beginner in c language and programming, I heard that an array's elements were stored in successive memory location.
- if I somehow manage to make memory location like this: what will happen if I declare an
int8_t arr[2]
, will it go wrong? - does compiler have a list of the allocated memory and check when it declares variable?
- 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:
- 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?"
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.
Calling
malloc
in a while loop is different from declaring an array such asint 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 ofmalloc
. The reason that there is0x20
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.
- 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.