C pointers (arrays) memory allocation (hexadecimal) - c

I was playing with memory addressing in C and I encountered a situation I cannot fully explain.
EDIT: the code is compiled by a c++ compiler. (g++)
#include <cstdlib>
#include <cstdio>
int main()
{
int* array[10]; //array of pointers to integers
for(int i = 0; i < 10; i++)
{
array[i] = (int*)malloc(sizeof(int));
*(array[i]) = i;
}
printf("\n");
for(int i = 0; i < 10; i++)
{
printf("%d:%p\n", *(array[i]), array[i]);
}
printf("\n");
int arr[10]; //array of integers
int* start = arr; //pointer to the first element (array decay)
for(int i = 0; i < 10; i++)
arr[i] = i;
printf("\n");
for(int i = 0; i < 10; i++)
{
printf("%d:%p\n", *(start + i), start + i);
}
printf("\n");
return 0;
}
Everything compile and works however I get strange memory addresses.
For the first array I get something like:
0:0x23e4010
1:0x23e4030 (32 bits between the addresses which is correct)
but for the second array I get:
0:0x7ffdaf876290
1:0x7ffdaf876294 (only 4 bits? or maybe they are bytes - but why the long addresses???)
Can someone explain this? (also is there a function to transform the hex into decimal without any effort?)

In the first instance, your array is an array of pointers. Each element is a pointer and, when you allocate memory for each pointer to point to, it's completely unrelated to the memory you allocate for other pointers in that array. They are in fact 32 bytes apart in this case, but that's just pure chance.
In the latter case, you are creating an array of integers which are all bunched together, or "contiguous", in memory. They will be adjacent, hence the pattern you see when you print their addresses, which are 4 bytes apart. Evidently, int on your system is 4 bytes wide (which is fairly common still).
The "long addresses" are due to your use of dynamic allocation: that'll be the area in virtual memory where your system happens to hold the heap. Nothing to worry about.
So there's nothing "strange" about it.

Int for Array uses 1byte.
Let address of:
- array[0]=5000
Then
- array[1]=5001
- array[2]=5002
- array[3]=5003
- array[4]=5004
- array[5]=5005
- array[6]=5006
- array[7]=5007
- array[8]=5008
- array[9]=5009
Now, You're assigning pointer.
Then address of Pointer:
*(array[0])=5010
*(array[1])=5011
*(array[2])=5012
*(array[3])=5013
*(array[4])=5014
*(array[5])=5015
*(array[6])=5016
*(array[7])=5017
*(array[8])=5018
*(array[9])=5019
Here You can easily see that the difference between array[i] and *(array[i]) will be always 10bytes.
This is because when any Array is called then only it allocates memory total size at once.
Now addresses of second:
Array arr is defined but not called. Hence, no memory will be allocated till you call that arr
Here, calling is for defining it
Now, first line says:
int arr[10];
That only defined the base address.
Then you gave that base address to *start by:
int* start=arr;
Hence pointer gets that address.
Clearly, Let:
Address of:
arr[0]=5020
Then:
*(start+0)=5020
Since, it is a pointer (not an Array) hence will take 4bytes.
Similarly, all addresses range will be:
arr[0]=5020 - 5023
arr[1]=5024- 5028
And so on..
Explanation to Allocation:
Whenever we define an Array, it defines only the Base Address.
Ex:
int a[10];
Will allocate base address, i.e., starting address, i.e., address for a[0];
Whenever you define a pointer, it will also allocate base address only.
Difference lies only in the allocation, i.e., array allocates 1byte and pointer allocates 4byte (GCC/ Linux/32bit Compiler) for a Pointer.

Related

Is there a way to print all memory addresses a variable is stored in?

I want to know if there is a way to print all the memory locations that say an int variable is stored in.
Example:
#include <stdio.h>
int main()
{
int x = 5;
int *y = &x;
printf("%p", (void*)y);
}
Example output: 0x100000000001
This will show the memory address that the first byte of x is stored in, but I want to see the memory address of each byte that it is stored in.
Is there any way to do this? Or do I just assume the following memory place values since they're consecutive?
i.e. the other memory locations of this int would be:
0x100000000002?
0x100000000003?
0x100000000004?
a way to print all the memory locations that say an int variable is stored in.
Sure. Form a loop [0...sizeof(int)).
int main() {
int x = 5;
void *y = &x;
for (size_t i = 0; i < sizeof x; i++) {
printf("%p\n", (void*)((char *)y + i));
}
}
If you know the variable type in the compilation time, you can use sizeof to determinate the variable memory size (in bytes) and then assume that the addresses range is from (char*)&var to (char*)&var + sizeof(var) - 1.
If the variable is received as an allocated memory, you better use malloc_usable_size from <malloc.h> in order to get the variable size and then find the addresses range.
Note that usually operating-systems allocates virtual memory for processes.

Dynamic memory allocation of 2d array

In this code, while we are dynamically allocating memory for the 2D array, after 4 address why it is taking a gap of 16 bytes but when we are statically allocating 2D array then it does not have such gap.... what is the reason behind this???
#include <stdio.h>
#include <stdlib.h>
int main()
{
int r = 3, c = 4, i, j, count;
int stat[r][c];
int *arr[r];
for (i=0; i<r; i++)
arr[i] = (int *)malloc(c * sizeof(int));
// Note that arr[i][j] is same as *(*(arr+i)+j)
count = 0;
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
arr[i][j] = ++count; // Or *(*(arr+i)+j) = ++count
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
printf("%d\n", *(arr+i)+j);
printf("\n\n");
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
printf("%d\n", *(stat+i)+j);
/* Code for further processing and free the
dynamically allocated memory */
return 0;
}
Because you are not allocating a 2D array. You are allocating a set of 1D arrays, and those allocations do not have to be contiguous (most malloc implementations reserve some bytes to store the size of the allocated block).
To dynamically allocate a "true" 2D array where number of rows and columns aren't known until runtime, you'd do something like this:
stat (*arr)[c] = malloc( sizeof *arr * r );
that would be contiguous like any "normal" 2D array.
But...
Strictly speaking, this behavior is undefined - since arr points to a VLA, the sizeof *arr expression must be evaluated at runtime, not at compile time, and arr is not a valid pointer value at that point. I've never seen this fail on any implementation I've used, but that doesn't mean it won't fail somewhere. If c were constant instead, like
stat (*arr)[3] = malloc( sizeof *arr * r );
then there wouldn't be a problem, and this would be the preferred way to dynamically allocate an Nx3 array.
If you need all array elements to be contiguous (such that you could traverse the entire array with a pointer or something like that), then the safest option is to allocate your memory as a 1D array:
stat *arr = malloc( sizeof *arr * r * c );
and compute the offsets manually:
x = arr[ i * r + j ];
If you want the convenience of 2D notation, you could try creating a pointer and setting to point to the beginning of the array, something like
stat (*ptr)[c] = (stat (*)[c]) arr;
but that kind of pointer aliasing is also undefined if the pointer types are not compatible, and we've no reason to expect that a pointer to T is compatible with a pointer to an array of T.
The comments on your question have the most essential advice - don't worry about where malloc puts your memory. There is no assurance that it will be in any order. It may locate allocations in pursuit of various optimizations or speculations, and may vary from one execution to the next. If nothing else, other memory allocations, calls to free, garbage collection (in languages with GC, that is) between your calls to malloc will affect the location of the next allocation.
This can also vary with compiler, compiler options, OS, etc.
As for the specific reason your allocations have a 16 byte gap, that's impossible to say without more, and likely very deep, insight into your scenario. BTW, you didn't include output of your printf in your question.
But if I had to guess, I'd say the memory manager was aligning the allocations up with memory boundaries...perhaps a 32-byte or 64-byte boundary.
You're allocating 4 * sizeof(int). If an int is 4 bytes on your system, that's 16 bytes. If your malloc likes to line things up to 32 bytes, that might explain the 16-byte gaps you're seeing.
But again...this is just a guess. The simple answer is...you shouldn't care.
But if you DO care for some reason, you probably need to do your own allocation. malloc a much larger chunk of memory, and then manage your own pointers and allocations internally.

Assigning the value of a pointer at a certain index in C

I'm trying to understand this code:
struct mys {
double d[128];
};
void my_func(int iters) {
int i;
struct mys *ptr = malloc(iters *sizeof(struct mys));
for(i = 0; i < iters; i++) {
ptr[i].d[0] = (double)i;
}
free(ptr);
}
What I know:
mys is of size 8 * 128 (size of double is 8, it's an array of 128 doubles)
*ptr is of size iters * (8 * 128)
What is going on here:
ptr[i].d[0] = (double)i;
?
What I know:
// ptr->d is the address of the first part of d
// same as (*ptr).d
// BECAUSE d IS A STRUCT
// ptr->d[i] is the actual value. so, 0.0000
// same as (*ptr).d[i]
Thanks in advance.
ptr[i] is the value at index i, so starts at 0.0000.
d is not initialized, it is just the name of the member of a struct. How can we just d here?
What I think:
*ptr is multiple (iters) structs.
So, ptr[0] is the first struct, ptr[1] is the second struct, etc.
ptr[i].d access the ith struct's d array.
ptr[i].d[0] accesses the first index of the d array. So the line above sets that number to double(i).
So this really only sets the first element of each struct to be 0. Am I right?
But when iters is 2, and I try:
for(int i = 0; i < iters; i++) {
printf("%p\n", ptr[200].d);
}
it still prints an address. Why is that?
What is going on here: ptr[i].d[0] = (double)i;?
This:
struct mys *ptr = malloc(iters *sizeof(struct mys));
allocates memory for an array of structs, called ptr.
This line of code:
ptr[i].d[0] = (double)i;
assigns i to the first cell of the array d, of the i-th struct, in the array ptr.
i is casted to double, because d is an array of doubles, and i is declared as int.
when iters is 2, and I try: for(int i = 0; i < iters; i++) { printf("%p\n", ptr[200].d); } it still prints an address. Why is that? Shouldn't it be out of range since ptr is only 2 structs?
This is definitely out of range, since arrays are 0-indexed.
However, that attempt invokes Undefined Behavior (UB), which means that you don't know how the code is going to behave. For example, in your computer it prints an address, in my computer it might cause a segmentation fault, and so on...
So this really only sets the first element of each struct to be 0. Am I right?
It copies the index i, converted to type double, into the first element of each struct. Otherwise you are right.
Regarding the expression ptr[200].d, this is the same as &(ptr[200]) because the array d[] is the sole element of a mys object. Because a double is eight bytes wide, each mys object occupies (8 bytes)(128) = 1 kiB. Therefore, &(ptr[200]) == ptr + 200*1024. The last is an address 200 kiB past the beginning of *ptr. Whether the address has meaning depends on whether anything meaningful is stored there.

Memory allocation using for loop

My Doubt is regarding only memory allocation so don't think about program output
#include<stdio.h>
int main(){
for(int i=0;i<20;i++){
char *str=malloc(sizeof(char)*6); //assuming length of each string is 6
scanf("%s",str);
insertinlinkedlist(str);
}
}
whenever i allocate memory here as shown above only the base address of char array will pass to linked list,and that is the memory block allocated for char array is inside main only and i am storing the base address of that array in str which is local to main and is passed to insetinlinkedlist
I want to ask whenever memory is allocated inside loop than why the number of
memory blocks(no of char arrays declared ) are created equal to n (number of time loop runs) since variable name is same we should be directed to same memory location
Note I have checked in compiler by running the loop all the times when loop runs memory the value of str is different
is The above method is correct of allocating memory through loop and through same variable "Is the method ensures that every time we allocate memory in above manner their will be no conflicts while memory allocation and every time we will get the address of unique memory block"
Now above doubt also creates a doubt in my mind
That if we do something like that
int main(){
for(int i=0;i<n;i++){
array[50];
}
}
then it will also create 50 array inside stack frame
malloc returns a pointer to the first allocated byte. Internally it keeps track of how much memory was allocated so it knows how much to free (you do need to insert calls to free() or you'll leak memory, by the way). Usually, it does this by allocating a little bit of memory before the pointer it gives you and storing the length there, however it isn't required to do it that way.
The memory allocated by malloc is not tied to main in any way. Currently main is the only function whose local variables have a pointer to that memory, but you could pass the pointer to another function, and that function would also be able to access the memory. Additionally, when the function that called malloc returns, that memory will remain allocated unless manually freed.
The variable name doesn't matter. A pointer is (to first approximation) just a number. Much like how running int a = 42; a = 20; is permitted and replaces the previous value of a with a new one, int *p = malloc(n); p = malloc(n); will first assign the pointer returned by the first malloc call to p, then will replace it with the return value of the second call. You can also have multiple pointers that point to the same address:
int *a = malloc(42);
int *b = malloc(42);
int *c = a;
a = malloc(42);
At the end of that code, c will be set to the value returned by the first malloc call, and a will have the value returned by the last malloc call. Just like if you'd done:
//assume here that f() returns a different value each time
//it's called, like malloc does
int a = f();
int b = f();
int c = a;
a = f();
As for the second part of your question:
for(int i=0;i<n;i++){
int array[50];
}
The above code will create an array with enough space for 50 ints inside the current stack frame. It will be local to the block within the for loop, and won't persist between iterations, so it won't create n separate copies of the array. Since arrays declared this way are part of the local stack frame, you don't need to manually free them; they will cease to exist when you exit that block. But you could pass a pointer to that array to another function, and it would be valid as long as you haven't exited the block. So the following code...
int sum(int *arr, size_t n) {
int count = 0;
for (size_t i = 0; i < n; i++) {
count += arr[i];
}
return count;
}
for(int i=0;i<n;i++){
int array[50];
printf("%d\n", sum(array, 50));
}
...would be legal (from a memory-management perspective, anyway; you never initialize the array, so the result of the sum call is not defined).
As a minor side note, sizeof(char) is defined to be 1. You can just say malloc(6) in this case. sizeof is necessary when allocating an array of a larger type.

C: State of memory during an array declaration

I recently submitted a small program for an assignment that had the following two functions and a main method inside of it:
/**
* Counts the number of bits it
* takes to represent an integer a
*/
int num_bits(int a)
{
int bitCount = 0;
while(a > 0)
{
bitCount++;
a = a >> 1; //shift to the right 1 bit
}
return bitCount;
}
/**
* Converts an integer into binary representation
* stored in an array
*/
void int2bin_array(int a, int *b)
{
//stopping point in search for bits
int upper_bound = num_bits(a);
int i;
for(i = 0; i < upper_bound; i++)
{
*(b+i) = (a >> i) & 1; //store the ith bit in b[i]
}
}
int main()
{
int numBits = num_bits(exponent);
int arr[numBits]; //<- QUESTION IS ABOUT THIS LINE
int2bin_array(exponent, arr);
//do some operations on array arr
}
When my instructor returned the program he wrote a comment about the line I marked above saying that since the value of numBits isn't known until run-time, initializing an array to size numBits is a dangerous operation because the compiler won't know how much memory to allocate to array arr.
I was wondering if someone could:
1) Verify that this is a dangerous operation
2) Explain what is going on memory wise when I initialize an array like that, how does the compiler know what memory to allocate? Is there any way to determine how much memory was allocated?
Any inputs would be appreciated.
That's a C99 variable length array. It is allocated at runtime (not by the compiler) on the stack, and is basically equivalent to
char *arr = alloca(num_bits);
In this case, since you can know the upper bound of the function, and it is relatively small, you'd be best off with
char arr[sizeof(int)*CHAR_BIT];
This array has a size known at compile time, will always fit everything you need, and works on platforms without C99 support.
It should be ok, it will just go on the stack.
The only danger is blowing out the stack.
malloc would be the normal way, then you know if you have enough memory or not and can make informed decisions on what to do next. But in many cases its ok to assume you can put not too big objects on the stack.
But strictly speaking, if you don't have enough space, this will fail badly.

Resources