Why does malloc returns a pointer? [closed] - c

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
While allocating static memory in c, it can be done quite simply. But while dealing with dynamic memory why do i have to deal with pointer. one explanation is that malloc allocates the memory and returns pointer so that it can be accessed but then why same does not happen in case of static memory?
Shouldn't it be simply accessed by its name?
for eg
int *arr = (int*)malloc(sizeof(int));

First, when a program executes malloc(n), there is no name. It is not possible to refer to the object by name because there is no name that refers to the space that malloc allocated.
Consider int *p = malloc(n);. This assigns the pointer that malloc returns to p. Note that p is the name of the pointer. It is not the name of the space. *p refers to the space.
We could add a feature to C that lets us bind names to allocated space, so that int &x = *p; caused x to refer to the space. But that is not often what we want to use allocated space for. Sometimes we want to allocate many things and organize them into a linked list or a tree or other structures where one element of a structure points to other structures. We would not want to have an individual name for every structure in the program—we want to work with them dynamically, using computed pointers. For example, consider how we might add up all numbers in an array:
int sum = 0;
for (int i = 0; i < N; ++i)
sum += array[i];
We would not want to write this loop as sum = array[0] + array[1] + array[2] + …;. Aside from being tedious, we do not know how many terms to write at compile time. We want this loop to be dynamic, for the elements to be computed while the program is running. Similarly, with a linked list, we want to write:
int sum = 0;
for (int *p = Head; p; p = p->next)
sum += p->value;
So we do not want a bunch of named variables for the allocated objects. We want to be able to manipulate them with pointers.

The way you propose to handle pointers would prevent half of the use cases of pointers.
They not only allow to access the content of the memory referenced by the pointer,
they also allow to change the memory addressed by the pointer, i.e. which part of memory it refers to.
Accessing the content of the referenced memory is done like
int* arr= malloc(sizeof(int)); /* Do not cast malloc. */
*arr = 1;
Changing the memory which is referenced is done by
free(arr); /* assuming it was initialised as above */
arr= malloc(sizeof(int)*2); /* different now */
(Strictly this does not guarantee the pointer to get a different value at the second malloc, but I did not want to make an example which leaks the first allocation by not freeing beforehand.)
And also changing the accessed memory without changing the pointer:
*arr=1; /* first */
*(arr+1) =2; /* second */

The way to understand "why does malloc returns a pointer?" is by understanding arrays in C. Array in c are sequential collection of elements. For statically allocating array we define as:-
int toys[20];
toys is an array of 20 elements of type integer. Here "toys" can be considered pointer and can be accessed like it.
*(toys) = 1; // setting first element i.e toys[0] = 1;
*(toys + 1) = 25; // setting second element i.e toys[1] = 25;
*(toys + 4) = 60; //setting 5th element i.e toys[4] = 60;
Now, looking into manual of malloc.
void * malloc(size_t size);
The malloc() function allocates size bytes of memory and returns a
pointer to the allocated memory.
Malloc always allocates memory in chunk (i.e, collection or array). so
p = malloc (8 )
allocates 8 bytes and return void type pointer of the 8 bytes, i.e. equivalent to static code below.
void test[8];
To get the pointer of desired type, the returned pointer is type casted as below:-
int * myToys = (int *) malloc ( sizeof(int) * 20 ); // same as, int mytoys[20];
PS:- Pointers and arrays are correlated. Malloc always returns array of bytes, so it returns pointer.

Related

How to properly allocate memory for an array pointer passed as an argument in C

I am mixed up on my pointers and references. I want to create a pointer in a main function and set it to null. I would like to pass that pointer to another function that creates an array on the heap, fills it, and returns the size of the created array.
I tried to find another article about this topic but failed to find one that allocated memory from within the function. The example code below illustrates the concept but I am not writing a program to accomplish any specific task.
int fillarray(/* pointer to an array */){
// malloc the array to size n
// fill array with n elements
return n;
}
int main(){
int* array = NULL;
int size = fillarray(/* pass the pointer by reference */);
for(int i = 0; i < size; i++) printf("%d\n", array[i]);
free(array);
return 0;
}
UPDATE:
Thank you all for your comments. I learned a ton about pointers working through this problem. The code below accomplishes what I need it to. Thank you #Lundin. Your answer led me to the actual solution. Thank you #ssd as well. Your visual helped me gain some intuition on what I was looking at in the code.
int fillarray(int** array){
*array = (int*)malloc(2 * sizeof(int));
(*array)[0] = 0;
(*array)[1] = 1;
return 2;
}
int main(){
int* array = NULL;
int size = fillarray(&array);
for(int i = 0; i < size; i++) printf("%d\t", array[i]);
return 0;
}
Strictly speaking there are no "references" in C, everything is passed by value. Although the term "pass by reference" is language agnostic and really just means pass an address to the data. (C++ has a language concept called references, but it's really just glorified read-only pointers.)
So to achieve what you want, you have to pass the address of the pointer itself. That way, the function can access the pointer and set it to point at a new address. Thus declare the function as int fillarray (int**)call the function as fillarray(&array). The result of malloc needs to be assigned to where the pointer-to-pointer points at - it points at the address of the original pointer declared variable in main().
As for allocating a variable size, you will have to add an additional plain integer parameter to the function for that.
I do agree & consent Lundin's answer but to be more conceptual, I'll add the drawing below, for I had the same pain in the past understanding pointers.
The first integer pointer below (int *a) is at memory address 4c4b40 and its value is set to zero (which means this pointer a is set to null).
The second integer pointer (int *b) is at memory address 4c4b48 and its value is set to 4c4b58 (which means, this pointer points to memory address 4c4b58 with a length of integer). If that address corresponds to variable int x = 16 (hexadecimal 10 is equal to 16), then dereferencing pointer b will give you an integer value of 16 (*b = 16 because x = 16).
The third memory is another character string pointer, which points to a memory address somewhere down below.
Returning to the answer:
If you are to change the address of the first pointer (a) in order to point to the variable x, then the function you're calling needs to receive the address of the pointer (not the pointer, itself); i.e. &a instead of a, which corresponds to 4c4b40. The function called will receive the address 4c4b40 as a memory address and change its value from 000000 to 4c4b58. The function decoration, of course, will contain an int **; for, if an integer pointer is an int *, a pointer to a pointer will be an int **.

Range of free on malloc returned memory [duplicate]

This question already has answers here:
How much memory would be freed if pointer is changed in C?
(3 answers)
Closed 7 years ago.
Given the following line:
int *digits = (int *) malloc(3 * sizeof(int));
Say we store the values 1, 2 and 3 in locations, digits[0], digits[1], digits[2]. As follows:
digits[0] = 1;
digits[1] = 2;
digits[2] = 3;
If the following line is called:
free(++digits);
Is the entire memory range returned by malloc freed, or just the int sized block currently pointed to by digits - at that time, digits[1]? Or is the correct way, to free the entire range by iteration, i.e:
for (i = 0; i < 3; i++)
{
free(digits[i]);
}
I am trying to understand the range of a call to free. Is the entire memory chunk returned by malloc freed, or is only a sub-portion, currently referenced by the pointer digits freed?
You must free() the exact same pointer value you get from malloc(). The entire blob of memory allocated by malloc() will be freed at once.
You can't use a pointer int the middle of the buffer returned to you by malloc() to free() it, but you must pass to free() exactly what malloc() returned you.
http://linux.die.net/man/3/malloc is pretty explicit about this.
As per rule malloc provide you with chunk of memory you demanded and return you start address of the chunk. you have to use digit to free memory as the only legal way to identify the allocated memory is pointer returned in your case it is digits

How is initializing an array different from mallocing memory?

I am new to C++. I am having trouble differentiating between initializing an array and mallocing memory. To me, they seem to accomplish the same purpose.
Specifically, I can initialize an array via int myArray[] = {1, 2, 3};. I can also use malloc to obtain memory and assign it to a void pointer. Later, I free this memory.
What is the difference between these two methods? Does a computer store the data in the same places and in the same ways?
In C++ there are two different ways you can allocate memory. The first way allocates memory on the stack.
int arr[] = {1,2,3};
int arr[3];
Both of these lines of code create an array of size 3 on the stack. The only difference is the first line also initializes the values in the array.
The second way you can allocate memory is on the heap. The amount of memory available on the heap is usually much larger than is available on the stack. The new and malloc operations allocate memory on the heap.
int* arr = (int*) malloc(100*sizeof(int));
int* arr = new int[100];
Both of these lines of code create an array of size 100 on the heap. Now here's the difference between the two. In C++ you should always use new because it ensures that the constructors for each element in your array are called. It is also much more type safe, unlike malloc which isn't type safe at all since it just returns a void* to a chunk of bytes that can be interpreted anyway you'd please.
Now if you're dynamically allocating memory, meaning you don't know the size of the array until runtime, you should always allocate it on the heap using new/malloc.
Last thing to note is how you free your memory, using delete/free.
free(arr); //arr was allocated with malloc
delete[] arr; //arr was allocated with new
If you allocated memory with new it must be freed with delete. You can't mix and match new/malloc with delete/free. Lastly delete[] frees an array of objects. If you only allocated a single object then you just use delete.
Object* myobj = new Object;
delete myobj;
In my opinion, this question does not belong to here. But I will answer it. You can do that with:
int* myArray = (int *) malloc(3 * sizeof(int));
This means that you are creating memory location with memory size 3 * sizeof(int) [i.e. the size of the integer data type in C], and you re returning an int pointer to this memory location. [i.e. a pointer that points to the beginning of it, and deal with it as it if contains integers]. These memory slots are converted to int * (using (int *)), and called myArray. myArray is an int array (and an int pointer). Because arrays are actually pointers in C. Then you do:
for (int i = 0; i < 3; i++)
myArray[i] = i + 1;
There could be some issues in malloc. Therefore, after the initialization always check if myArray == NULL. If this is case, fix the error, and dont initialize the array with $\{1,2,3\}$. Otherwise, you will get a segmentation fault.
I wish I am not vague to you. But since you are using C++, I would suggest you use the new operator instead. you would do:
int myArray[] = new int[3];

How to get the size of dynamically allocated 2d array

I have dynamically allocated 2D array.
Here is the code
int **arrofptr ;
arrofptr = (int **)malloc(sizeof(int *) * 2);
arrofptr[0] = (int *)malloc(sizeof(int)*6144);
arrofptr[1] = (int *)malloc(sizeof(int)*4800);
Now i have to know that how many bytes are allocated in arrofptr,arrofptr[0],arrofptr[1]?
is there any way to know the size?
if we will print
sizeof(arrofptr);
sizeof(arrofptr[0]);
sizeof(arrofptr[1]);
then it will print 4.
You can't find size of arrofptr, because it is only a pointer to pointer. You are defining an array of arrays using that. There's no way to tell the size information with only a pointer, you need to maintain the size information yourself.
The only return value you get from malloc() is a pointer to the first byte of the allocated region (or NULL on failure). There is no portable, standard, way of getting the associated allocation size from such a pointer, so in general the answer is no.
The C way is to represent arrays and buffers in general with a pair of values: a base address and a size. The latter is typically of the type size_t, the same as the argument to malloc(), by the way.
if you want to keep track of the size of an allocated block of code you would need to store that information in the memory block that you allocate e.g.
// allocate 1000 ints plus one int to store size
int* p = malloc(1000*sizeof(int) + sizeof(int));
*p = (int)(1000*sizeof(int));
p += sizeof(int);
...
void foo(int *p)
{
if (p)
{
--p;
printf( "p size is %d bytes", *p );
}
}
alt. put in a struct
struct
{
int size;
int *array;
} s;
You can't get the length of dynamically allocated arrays in C (2D or otherwise). If you need that information save it to a variable (or at least a way to calculate it) when the memory is initially allocated and pass the pointer to the memory and the size of the memory around together.
In your test case above sizeof is returning the size of the pointer, and thus your calculation the size of the pointers is usually 4, this is why you got 4 and is likely to have the trivial result of 4, always.

What causes this integer pointer reassignment to crash?

I am new to C and i have this question. why does the following code crash:
int *a = 10;
*a = 100;
Because you are trying to write 100 to the memory location 0x0000000A which is probably not allocated to your program. That is,
int *a = 10;
does not mean that the pointer 'a' will point to a location in memory having the value of 10. It means it is pointing to address 10 (0x0000000A) in the memory. Then, you want to write something into that address, but you don't have the "rights" to do so, since it is not allocated
You can try the following:
int *a = malloc(sizeof(int));
*a = 100;
This would work, although horribly inefficient. If you only need a single int, you should just put it into the stack, not the heap. On a 32-bit architecure, a pointer is 32 bits long, and an int is 32 bits long too, so your pointer-to-an-int structure takes up (at least) 8 bytes of memory space this way instead of 4. And we haven't even mentioned caching issues.
You need to assign the pointer to a memory location, not arbitrary value (10).
int cell = 10;
int *a = &cell; // a points to address of cell
*a = 100; // content of cell changed
See my answer to another question, about being careful with C.
I would like to propose a slight change in the use of malloc(), for all the answers that suggest using it to allocate memory for the int. Instead of:
a = malloc(sizeof(int));
I would suggest not repeating the type of the variable, since that is known by the compiler and repeating it manually both makes the code more dense, and introduces an error risk. If you later change the declaration to e.g.
long *a;
Without changing the allocation, you would end up allocating the wrong amount of memory ( in the general case, on 32-bit machines int and long are often the same size). It's, IMO, better to use:
a = malloc(sizeof *a);
This simply means "the size of the type pointed at by a", in this case int, which is of course exactly right. If you change the type in the declaration as above, this line is still correct. There is still a risk, if you change the name of the variable on the left hand side of the assignment, but at least you no longer repeat information needlessly.
Also note that no parenthesis are needed with sizeof when using it on actual objects (i.e. variables), only with type names, which look like cast expressions. sizeof is not a function, it's an operator.
Because you've never allocated any memory for a. You've just allocated some stack space for a pointer to a.
int *a = NULL;
a = malloc (sizeof (int));
if (a != NULL)
{
*a =10;
}
Will work.
Alternatively you could give a the address of some existing variable, which would work as well.
i.e.
int a* = NULL;
int b = 10;
a = &b;
This will now mean that doing something like
*a = 100;
will also set b to be == 100
Check out this:
http://home.netcom.com/~tjensen/ptr/pointers.pdf
The following line,
int *a = 10;
defines a pointer to an integer a. You then point the pointer a to the memory location 10.
The next line,
*a = 100;
Puts the value 100 in the memory location pointed to by a.
The problem is:
You don't know where a points to. (You don't know the value of memory location 10)
Wherever a points to, you probably have no right changing that value. It's probably some other program/process's memory. You thief!
Because You declare a pointer to int, initialize the pointer to 10 (an address) and then try to assign a value to an int at this address. Since the memory at address 10 does not belong to your process, You get a crash. This should work:
int *a;
a = malloc(sizeof(int));
*a = 10;
printf("a=%i\n", *a);
free(a);
Does this code even compile? 10 isn't convertible to an int *, unless you cast it like so:
int *a = (int *) 10;
*a = 100;
In that case, you're trying to write 100 into the memory address at 10. This isn't usually a valid memory address, hence your program crashes.
It's probably crashing because you are assigning the pointer to some part of memory which you don't have access to and then you're assigning some value to that memory location (which you're not allowed to do!).
You could also write it as:
int* a = 10;
*a = 100;
Note the different spacing on the first line. It's not a popular style, but I personally think it's clearer. It has exactly the same meaning to the compiler.
Then, read it out loud:
"Pointer-to-int 'a' becomes 10"
"Value-pointed-to-by 'a' becomes 100"
Substituting the actual value:
"Value-pointed-to-by 10 becomes 100"
... at which you realise that 10 is unlikely to point to a piece of memory you can use.
You would pretty much never assign to a pointer with a literal:
int* ptr = (int*)10; // You've guessed at a memory address, and probably got it wrong
int* ptr = malloc(sizeof(int)); // OS gives you a memory address at runtime
I guess there might be some very low level jobs where you directly specify absolute memory addresses. Kernel implementation for example?
Okay, trying to give the simplest explanation today, while trying to give you more detailed picture about it all. Lets add some parentheses shall we?
(int*) a = 10;
(*a) = 100;
You attempt to write four bytes into the address-range [10-13]. The memory layout of your program starts usually higher, so your application does not accidentally overwrite anything from where it could and still function (from .data, .bss, and stack for instance). So it just ends up crashing instead, because the address-range has not been allocated.
Pointer points to a memory location and C static typing defines a type for a pointer. Though you can override the pointer easily. Simply:
(void*) v = NULL;
Here we go further to things. What is a null pointer? It's simply pointer that points to address 0.
You can also give a struct type for your pointer:
struct Hello {
int id;
char* name;
};
...
struct Hello* hello_ptr = malloc(sizeof Hello);
hello_ptr->id = 5;
hello_ptr->name = "Cheery";
Ok, what is malloc? Malloc allocates memory and returns a pointer to the allocated memory. It has a following type signature:
void* malloc(size_t size);
If you do not have a conservative garbage collector, it is likely that your memory won't end up being freed automatically. Therefore, if you want to get the memory back into use from what you just allocated, you must do:
free(hello_ptr);
Each malloc you do has a size-tag in it, so you do not need to state the size of the chunk you pointed for free -routine.
Ok, yet one thing, what does a character string look like in memory? The one similar to "Cheery" for instance. Simple answer. It's a zero-terminated array of bytes.
0.1.2.3.4.5. 6
C h e e r y \0

Resources