Pointers and dynamic memory in C and C++ - c++

A few days ago I had to use C and when working with pointers I got a little surprise.
An example in C:
#include <stdio.h>
#include <stdlib.h>
void GetPointer(int* p) {
p = malloc( sizeof(int) );
if(p) {
*p = 7;
printf("IN GetPointer: %d\n",*p);
} else {
printf("MALLOC FAILED IN GetPointer\n");
}
}
void GetPointer2(int* p) {
if(p) {
*p = 8;
printf("IN GetPointer2: %d\n",*p);
} else {
printf("INVALID PTR IN GetPointer2");
}
}
int* GetPointer3(void) {
int* p = malloc(sizeof(int));
if(p) {
*p = 9;
printf("IN GetPointer3: %d\n",*p);
} else {
printf("MALLOC FAILED IN GetPointer3\n");
}
return p;
}
int main(int argc, char** argv) {
(void) argc;
(void) argv;
int* ptr = 0;
GetPointer(ptr);
if(!ptr) {
printf("NOPE\n");
} else {
printf("NOW *PTR IS: %d\n",*ptr);
free(ptr);
}
int* ptr2 = malloc(sizeof(int));
GetPointer2(ptr2);
if(ptr2) {
printf("NOW *PTR2 IS: %d\n",*ptr2);
free(ptr2);
}
int* ptr3 = GetPointer3();
if(ptr3) {
printf("NOW *PTR3 IS: %d\n",*ptr3);
free(ptr3);
}
return 0;
}
The output:
IN GetPointer: 7
NOPE
IN GetPointer2: 8
NOW *PTR2 IS: 8
IN GetPointer3: 9
NOW *PTR3 IS: 9
In this example, the first pointer will only have "value" inside the GetPointer method. Why using malloc inside lasts only for the lifetime of the method?
I tried this in C++ and got the same behaviour. I thought it would retain its value, but no. I found a way through, though:
void GetPointer(int*& p) {
p = new int;
if(p) {
*p = 7;
printf("IN GetPointer: %d\n",*p);
} else {
printf("MALLOC FAILED IN GetPointer\n");
}
}
In C I can't do this trick. Is there a way to do the same in C or I have to be careful and "malloc" the pointer before attempting to give it a value?

If you want to reassign what the pointer points to in C, you have to use int**, ie a pointer to a pointer.
That is because pointers are copied by value as arguments, so if want the change made in the pointers pointee to be visible outside the scope of the function, you need another level of indirection.

this
void GetPointer(int* p) {
p = malloc( sizeof(int) );
if(p) {
*p = 7;
printf("IN GetPointer: %d\n",*p);
} else {
printf("MALLOC FAILED IN GetPointer\n");
}
}
does absolutely nothing part from creating a memory leak.
the reason it doesn't do anything is that you pass a copy of the pointer to the function (int* p), if you want to change what p points to you need to pass the address of the pointer instead.
void GetPointer(int** p)

void GetPointer(int** pp) {
int *p = malloc( sizeof(int) );
if(p) {
*p = 7;
printf("IN GetPointer: %d\n",*p);
} else {
printf("MALLOC FAILED IN GetPointer\n");
}
*pp = p;
}

In void GetPointer(int* p) you are losing the pointer pointing to the dynamic memory as soon as you exit the function block.
Try using pointer to pointer approach:
GetPointer(int ** p) {
*p = malloc( sizeof(int) );
if(*p) {
**p = 7;
printf("IN GetPointer: %d\n",**p);
} else {
printf("MALLOC FAILED IN GetPointer\n");
}
}

p = malloc( sizeof(int) );
malloc( sizeof(int)); will return a pointer which is then assigned to p. But p is local to GetPointer,since the pointer itself is passed by value to it.
+----+
| |
xx +----+ malloc returns this block
+----+
| |
xx +----+ local variable p is assigned this block
+----+
| 7 |
xx +----+ p modifies value of this block
Function ends and so does p leaving behind a memory leak
+----+
| 7 |
xx +----+ No one points to it anymore
For GetPointer2 and GetPointer3 you do a malloc,
+----+
| |
yy +----+ malloc returns some other block

For the first call to GetPointer, you need to pass in a pointer to a pointer to an int. (unlike C++, which allows reference passing with the & operator in the function signature, C always passes things in by value, which means that your code is passing in a copy of ptr into the GetPointer function.) You need to pass in the address of that pointer (i.e. the location in memory where the pointer ptr is stored so that code inside the GetPointer method can put something in that location, thereby modifying ptr itself.
i.e. the call should be:
GetPointer(&ptr);
and the functions should look like:
void GetPointer(int** p) {
*p = malloc( sizeof(int) );
if(*p) {
**p = 7;
printf("IN GetPointer: %d\n",**p);
} else {
printf("MALLOC FAILED IN GetPointer\n");
}
}

Related

ESP32 Arduino ps_malloc works but not if i wrap it in a function [duplicate]

I have a segmentation fault in the code below, but after I changed it to pointer to pointer, it is fine. What is the reason?
void memory(int * p, int size) {
try {
p = (int *) malloc(size*sizeof(int));
} catch(exception& e) {
cout << e.what() << endl;
}
}
It does not work in the main function as below:
int *p = 0;
memory(p, 10);
for(int i = 0; i < 10; i++)
p[i] = i;
However, it works like thi .
void memory(int ** p, int size) { `//pointer to pointer`
try {
*p = (int *) malloc(size*sizeof(int));
} catch(exception& e) {
cout<<e.what()<<endl;
}
}
int main()
{
int *p = 0;
memory(&p, 10); // Get the address of the pointer
for(int i = 0; i < 10; i++)
p[i] = i;
for(int i = 0; i < 10; i++)
cout << *(p+i) << " ";
return 0;
}
Because you're wanting to get a pointer value back from the operations done in the function. malloc allocates memory and gives you an address for that memory.
In your first example, you store that address in the local argument variable p, but since it's just the argument, that doesn't make it back to the main program, because C/C++ are pass-by-value by default - even for pointers.
Main Function malloc
p p allocated
+---+ +---+
| 0 | | 0 | A
+---+ +---+
becomes...
p p allocated
+---+ +---+
| 0 | | ------------> A
+---+ +---+
and thus when main reads p, it gets 0, not A.
In your working code, you follow the pointer passed to an address, and that address gives you the location of the pointer variable in the main program. You update the pointer value at that address, which the main program can then look up the value of to use as its memory location - thus passing the address returned by malloc back to the main program for use.
Main Function malloc
p p allocated
+---+ +---+
| 0 |<------- | A
| | | |
+---+ +---+
becomes...
p p allocated
+---+ +---+
| |<------- |
| ----------------------> A
+---+ +---+
and thus when main reads p, it gets A.
A pointer stores the address at which the data is stored. Passing a pointer to a function means giving it the address of the data. However, here you have no address for the data until calling malloc. So instead you need to pass the address of the pointer (i.e. pointer to pointer). This allows memory to take the address of the pointer p and set p to point to the area of memory it allocates for the data.
In C, you have only pass-by-value. So your function memory() gets it own local-only copy of p. malloc inside memory() assigns only to the copy of p that is local to the function. When memory() returns to main(), the copy of p from main is unchanged. In C++, you solve this by using pass-by-reference, like this:
void memory(int*& p, int size)
In C, you use double pointers to achieve similar results.
In your first call to memory:
void memory(int * p, int size)
Realize that you are passing a VALUE to memory(), not an address. Hence, you are passing the value of '0' to memory(). The variable p is just a copy of whatever you pass in... in contains the same value but does NOT point to the same address...
In your second function, you are passing the ADDRESS of your argument... so instead, p points to the address of your variable, instead of just being a copy of your variable.
So, when you call malloc like so:
*p = (int *) malloc(size*sizeof(int));
You are assigning malloc's return to the value of the variable that p points to.
Thus, your pointer is then valid outside of memory().
The first example does not work because the pointer parameter is not the pointer in main, it just holds the same value.
You need a pointer to pointer because you need to return the value of the newly allocated pointer.
There is three ways to return that value (2 if you use C):
use a pointer, here it is a pointer to pointer
use a reference, here it is a reference to pointer
use the return value of the function, so make memory return a int * instead of void
The third way has definitely my preference.
(and not, I won't admit you could also use a global, it's not a fourth way but an horror).
You don’t need to use a pointer to pointer, but a referenced pointer, i.e., a * &, not just *.
Regarding,
memory(p, 10); // Get the address of the pointer
This just sends the p value, not the address of the p. It sends (*p). if the address of p is 123 and its value is 50, it sends 50 to the function.
And at the memory function it makes a new pointer with new address like 124 and it contains 50; and it will allocate the memory and write the start of the allocated memory to 124, not 123, so p at the main still contains 50. So you did nothing! You can control this with this code.
#include <iostream>
#include <conio.h>
#include <exception>
using namespace std;
void memory(int* p, int size) { // *************pointer to pointer` is a must**********
try {
p = new int[size];
p[0] = 100;
} catch(bad_alloc &e) {
cout << e.what() << endl;
}
}
int main()
{
int *p = 0; ******you can do you should do this*******
p = new int;
/* p = malloc(sizeof(int)); // This just changes the value inside
// of p. It is unnecessary.
And you will lose a address from memory :) And possibly it
will be unsafe if you free p may, you just
free one address
*/
/* Before using a pointer, always allocate its memory, else
you'll get frequent system crashes and BSODs */
memory(p, 10); // Get the address of the pointer // You are getting nothing
cout << p[0];
// We set p[0] to 100, but it will write a garbage value here.
// Because the value inside of p didn't change at the memory
// function, we sent just the value inside of p.
getch();
return 0;
}
I corrected the code... read the comments and all will be clear...
#include <iostream>
#include <conio.h>
#include <exception>
using namespace std;
void memory(int* p, int size) { // Pointer to pointer` not needed
try {
p = new int[size];
} catch(bad_alloc &e) {
cout<<e.what()<<endl;
}
}
int main()
{
//int *p = 0; Wrong ... no memory is assigned and then
// you are passing it to a function
int *p;
p = new int; // p = malloc(sizeof(int));
/* Before using a pointer, always allocate its memory, else
you'll get frequent system crashes and BSODs */
memory(p, 10); // Get the address of the pointer
for(int i = 0; i < 10; i++)
p[i] = i;
for(int i = 0 ; i < 10; i++)
cout << *(p+i) << " ";
getch();
return 0;
}

Are double pointers necessary?

void test(int *p2) {
*p2 = 3;}
int main()
{
int* p1, x = 5;
p1 = &x;
test(p1); // p1 and p2 are pointing to the same address which is x's address
printf("%d", x); //prints 3
this example 2 pointers pointing to the same address, which passing to the function by reference.
Now take this 2nd example
void test(int **p2) {
**p2 = 3;
}
int main()
{
int* p1, x = 5;
p1 = &x;
test(&p1); // p2 is pointing to p1 address
printf("%d", x);
so are double pointers necessary in these type of situations? especially with structured linked lists?
typedef struct NOde {
int data;
struct NOde* next;
}node;
void test(node *head) {
node* new_node = (node*)malloc(sizeof(node));
new_node->data = 5;
new_node->next = head;
head= new_node;
}
int main()
{
node* head=NULL;
test(head);
and why in this one, the head values in the main still NULL if it same concept as above?
Pointers (*p) are sufficient when you want to change the contents of the address the pointer is pointing at.
Double star pointers (**p) are necessary when you want to change the address the pointer is pointing at.
In the following code, inspect the outcome of the second printf statements especially.
#include <stdio.h>
#include <stdlib.h>
void swapValues(int *p, int val) {
*p = val;
}
void swapPointers(int **p, int *val) {
*p = val;
}
int main() {
int x, y;
int *p1 = &x;
int *p2 = &x;
x = 3;
y = 5;
printf("x = %d y = %d p1 = %d p2 = %d\n", x, y, *p1, *p2);
printf("p1 = %p p2 = %p\n", p1, p2);
swapValues(p1, y);
printf("x = %d y = %d p1 = %d p2 = %d\n", x, y, *p1, *p2);
printf("p1 = %p p2 = %p\n", p1, p2);
x = 3;
y = 5;
swapPointers(&p2, &y);
printf("x = %d y = %d p1 = %d p2 = %d\n", x, y, *p1, *p2);
printf("p1 = %p p2 = %p\n", p1, p2); // observe value of p2 here
return 0;
}
In C, all function calls are made by value. Which essentially means that the called function always gets its own copy of the arguments you pass to it. Same goes with the value you return from the function. There is always a copy of this value given back to the caller. The moment a function finishes execution, all arguments passed to it and local variables declared within it cease to exist.
For example:
int add(int a, int b)
{
int result = a + b;
return result;
}
int main()
{
int p = 3, q = 5;
int r = add(p,q);
}
In this case, a and b are copies of p and q respectively, and r is a copy of result. p, q and result no longer exist after add() has finished execution.
Now, this is fine for many common use-cases as in the example above. But what if you want to change the value of one of the variables in the calling function from within the called function? You then need to pass the address of the variable, so that the called function can indirectly access the variable in the calling function and update it.
Example:
void inc(int *p)
{
*p = *p + 1;
}
int main()
{
int a = 5;
inc(&a);
}
In this case, the called function gets a copy of the address of a, called p, using which it is able to update the memory location holding a indirectly. This is called dereferencing a pointer.
Now, to address your question, we need to take this one step further - what if we need to update a pointer in the calling function? We need to pass a pointer to the pointer - also called a double pointer.
In your example, we need to update head, which is already a pointer to a Node. So we need to pass the address of head, for which we need a double pointer.
Hence your code should be:
void test(node **phead)
{
node* new_node = (node*)malloc(sizeof(node));
new_node->data = 5;
new_node->next = *phead;
/* Note the dereferencing here - we update `head` indirectly through a pointer */
*phead = new_node;
}
test(&head);
Otherwise, we would be passing around a copy of head, which is a pointer, using which you can access the node that head points to, but not head itself. If you increment this pointer within your function, the change is not reflected outside, because this copy ceases to exist the moment the function returns.
PS: C++, unlike C, supports call by reference, which means the language transparently handles the pointer management and lets you directly update variables passed to you 'by reference'.
In your case no, because to assign the value you only need one pointer.
void test(int *p2) {
*p2 = 3;
}
Pointers to pointers are useful when you want to change the pointer.
A common use of pointers to pointers is methods that create something, but want to return something other than the pointer itself, e.g.
myerror_t create_foo(foo_t **p, int a, int b, int c)
{
if (a < 0 || b < c) return MYERR_INVALID_ARG;
*p = malloc(sizeof foo_t);
p->x = a * b * c;
return MYERR_SUCCESS;
}
Note that in C++, sometimes references are used when changing the value, and they can function in a very similar way.
void test(int &p2) {
p2 = 3;
}
Also note in C++, that throwing an exception, often from a constructor, is more common that a create_foo style method.
Foo::Foo(int a, int b, int c)
{
if (a < 0) throw std::invalid_argument("Foo a < 0");
if (b < c) throw std::invalid_argument("Foo b < c");
x = a * b * c;
}
If a factory function is desired, it might return the pointer and throw exceptions.
double pointers are needed if you are going to change the pointer itself in the function
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int value1 = 10;
int value2 = 20;
void choose(int x, int **pointerToValue)
{
switch(x)
{
case 0:
*pointerToValue = &value1;
break;
case 1:
*pointerToValue = &value2;
break;
default:
*pointerToValue = NULL;
}
}
int main()
{
int *ptr;
int choice;
choose(choice = rand() & 1, &ptr);
//ptr value was changed in the function
printf("Choice = %d, value = %d\n", choice, ptr ? *ptr : 0);
}
Are double pointers necessary?
TL;DR:
The moment a function shall change the value of a pointer defined by the calling function, then yes, they are (and can even become triple, quatuple, ... pointers).
Longish answer:
To have a function change a variable of type T and this variable is defined by the caller, the caller needs to pass to the function a pointer to T, that is a T*.
The function then needs to dereference the T* variable using the * operator as shown in your 1st snippet:
void test(int *p2) {
*p2 = 3; /* p2 is dereferenced, so the assignment works on the variable it is pointing to. */
}
So if then T already is a pointer type then T* would be a pointer to a pointer.
This latter case should be the appearing within the last snippet you show. And it shall be handled exactly as in the 1st snippet. node * head shall be changed within test2(). So pass the address of head;
test2(&head);
To be able to do so the parameter of test2 need to be defined as a pointer to the type of head. head is node*, so a pointer to is is node**.
void test2(node ** phead)
To then change the value of the caller's head inside the function the pointer to head, namely phead needs be dereferenced:
*phead = ....
why in this one, the head values in the main still NULL if it same concept as above?"
Comparing the lines of your last snippet to the versions in my answer, you see that your code in fact is not using the "same concept" but misses a level of indirection, which your 1st snippet indeed uses ...;)
You would only pass a double (or triple, or whatever) pointer to a function if you need the function to write a new pointer value to the parameter, or if you're dealing with multiple-dimensioned data (an array of pointers to arrays (of pointers to arrays of ...)).
If you want a function to write to a parameter of type T, then you need to pass a pointer to T:
void foo( T *p )
{
*p = new_T_value(); // write a new value to the thing p points to
}
void bar( void )
{
T var;
foo( &var ); // foo writes a new value to var
}
Now let's replace T with the pointer type P *:
void foo( P **ptr )
{
*ptr = new_pointer_to_P_value;
}
void bar( void )
{
P *var;
foo( &var ); // write a new pointer value to var
}
Once more for emphasis, replace P with Q *:
void foo( Q ***ptr )
{
*ptr = new_pointer_to_pointer_to_Q_value;
}
void bar( void )
{
Q **var;
foo( &var ); // write a new value to var
}
The semantics are the same in all three cases, all that's changed is the level of indirection. For N levels of indirection in bar, you need N+1 levels of indirection in foo.
The other case for multiple indirection is multiple-dimensioned data (arrays of pointers to arrays of pointers to ...). For example:
void create_2d_arr( int ***arr, size_t rows, size_t cols )
{
*arr = malloc( rows * sizeof *(*arr) );
if ( *arr )
{
for ( size_t i = 0; i < rows; i++ )
{
(*arr)[i] = malloc( cols * sizeof *(*arr)[i] )
{
for ( size_t j = 0; j < cols; j++ )
{
(*arr)[i][j] = initial_value;
}
}
}
}
}
As to your example:
void test(node *head) {
node* new_node = (node*)malloc(sizeof(node));
new_node->data = 5;
new_node->next = head;
head= new_node;
Yes, in this case, if you want the change to head to be seen in main, you have to pass a pointer to the pointer:
void test(node **head) {
node* new_node = (node*)malloc(sizeof(node));
new_node->data = 5;
new_node->next = *head;
*head= new_node;
}
int main( void )
{
...
test( &head );
...
}
It's not necessary double pointer because p2 is in the scope of the function so in the main function is not visibile. And you don't want to change the pointer address but only the value of the pointed variable.
If ypu want to change a variable in a function you should pass it by reference in C or C++ meaning.
Consider your example of a singly-linked list. The variable head has a pointer type.
node* head=NULL;
So to change it in the function test you need to pass the variable by reference. For example
A C implementation passing by reference
void test( node **head, int data )
{
node *new_node = ( node* )malloc( sizeof( node ) );
new_node->data = data;
new_node->next = *head;
*head= new_node;
}
and a C++ implementation passing by reference
void test( node * &head, int data )
{
head = new node { data, head };
}
Without passing the head node by reference in the C function implementation the function deals with a copy of the value stored in head. You can imagine the function and its call the following way
test( head, 5 );
//...
void test( /*node *parm_head, int data*/ )
{
node *parm_head = head;
int data = 5;
node *new_node = ( node* )malloc( sizeof( node ) );
new_node->data = data;
new_node->next = *head;
*head= new_node;
}
That is function parameters are its local variables.
Consider another example when you need ay first to allocate an array to pointers to strings. For example
char **strings = malloc( 10 * sizeof( char * ) );
for ( size_t i = 0; i < 10; i++ )
{
strings[i] = malloc( 100 );
}
Now if you want to reallocate the original array by adding one more string then you gave to pass a pointer to this double pointer. For example
void add_one_more_string( char ***strings )
{
char **tmp = realloc( *strings, 11 ( sizeof( char * ) );
if ( tmp != NULL ) *stringvs = tmp;
//…
}
and call the function like
add_one_more_string( &strings );

what happens when a pointer is passed as a pointer to a pointer inside another function?

So can someone explain what would happen if I pass ...*p as the argument name for the foo function
int main()
{
int i = 10;
int *const p = &i;
foo(&p);
printf("%d\n", *p);
}
void foo(int **p)
{
int j = 11;
*p = &j;
printf("%d\n", **p);
}
Don't do that. You'll have a pointer to an undefined memory location on the stack. Any other function call between foo(&p); and printf("%d\n", *p); is bound to overwrite that memory location with new data.
Let's look at a simple example here! We have a function print_address, which takes an address and prints it. We're gonna print the address of an int, as well as the address of a pointer to that int, and a pointer of a pointer to that int.
#include <stdio.h>
void print_address(void* addr) {
printf("Address: %p\n", addr);
}
int main()
{
int value = 0;
int* value_ptr = &value;
int** value_ptr_ptr = &value_ptr;
print_address(&value);
print_address(&value_ptr);
print_address(&value_ptr_ptr);
return 0;
}
When I run this code, I get the following output:
Address: 0x7fffa4936fec
Address: 0x7fffa4936ff0
Address: 0x7fffa4936ff8
The first address is to value, the second address is to value_ptr, and the third address is to value_ptr_ptr. Each address is a little higher than the previous one, because each variable has been stored a little higher up on the stack.
The same thing happens with function calls. When we call a function, the memory for all the local variables in that function is stored a little higher up on the stack then the memory for all the local variables in the current function:
#include <stdio.h>
void print_address(void* addr) {
printf("Address: %p\n", addr);
}
void f3(int*** ptr) {
print_address(ptr);
}
void f2(int** ptr) {
print_address(ptr);
f3(&ptr);
}
void f1(int* ptr) {
print_address(ptr);
f2(&ptr);
}
int main()
{
int value = 0;
f1(&value);
return 0;
}
This time when I ran it, the output was
Address: 0x7ffeca71dc2c
Address: 0x7ffeca71dc08
Address: 0x7ffeca71dbe8
If you notice, the gaps between addresses are higher, but that's because of the extra stack space it takes to do a function call.
j is destoyed after exiting foo, so doing anything with it after foo calling in main is incorrect, until you reset it on another object (I mean printf("%d\n", *p)).
Well, what you're doing is passing pointer on pointer on integer.
As you could see, pointers are often used to pass arrays:
void print_array(int* a, int n) {
for (int i = 0; i < n; i++)
printf("%d ", a[i]);
printf("\n");
}
And pointers on pointers are used to pass two-dimensional arrays, for example in int main(int argc, char** argv) { ... } argv is array of strings or array of arrays of char-s.
You can't pass *p, but let's say you could...
It looks like you are trying to get your function to update a parent variable - and passing &p is the correct way to do it. But you are adding one too many dereference. I highly recommend you read this: https://boredzo.org/pointers/
// Let's assume you only have 4 memory locations for variables: 1 2 3 and 4.
// let's call these m[1] m[2] m[3] and m[4]
// i is at 1, p is at 2, j is at 3, and the p inside the function is at 4.
// let's call that second p, q rather
// so you have: m[1..4] = { i, p, j, q }
// now execute the code in your head:
int main()
{
int i = 10; // m[1] = 10
int *const p = &i; // m[2] = 1
foo(&p); // foo(2)
printf("%d\n", *p); // printf m[2]
}
void foo(int **q) // q = m[m[2]] = m[1] = 10
{
int j = 11; // m[3] = 11
*q = &j; // m[10] = 3 // segfault!
printf("%d\n", **q); // printf m[m[10]] = m[3] = 11 // if it didnt' segfault
}
It looks like this is what you are trying to do:
#include <stdio.h>
void b(int *q,int n) {
*q=n;
}
int main() {
int i=123;
int *p=&i; // *p and i are now synonymous
printf("%i ",i);
printf("%i ",*p); // same thing
b(p,111);
printf("%i ",i);
b(&i,111);a // same thing
printf("%i ",i);
}

Try to modify const reference

I've got an argument with my co-workers.
Once I did try to modify constant reference.
Sample of code is below:
#include <cstdio>
#include <cstdlib>
using namespace std;
int main(int argc, char const *argv[])
{
const int* A = NULL;
printf("A = %p\n", A);
int** pA = const_cast<int**>(&A);
*pA = new int(5);
if (pA != NULL)
printf("pA = %p, value = %d\n", pA, *pA);
else
printf("pA null pointer\n");
if (A != NULL)
printf("A = %p, value = %d\n", A, *A);
else
printf("A null pointer\n");
return 0;
}
Everything works fine and the log is
A = 00000000
pA = 0028FED8, value = 4068760
A = 003E1598, value = 5
I think it works that way:
I create a const pointer variable A with '0' (zero) value is stack. It is local variable wich occupies 4 bytes of memory in stack.
then I create a pointer to pointer variable, I cast away constant modification and take address of the variable
I think this code works fine and will not lead to a bug. But I need some kind of explanations. Am I right?
const int *a and int * const a are different.
Case 1
[const is used on *a]
Here the value of a is constant. The address pointed by a can be changed.
const int *a = malloc(sizeof (int));
if (a)
{
//*a = 10; //not allowed
a = malloc(sizeof (int));; //allowed
}
Case 2
[const is used on a]
Here the address of a is constant. The value of a can be changed.
int * const a = malloc(sizeof (int));
if (a)
{
*a = 10; //allowed
//a = malloc(sizeof (int));; //not allowed
}
EDIT:
As suggested by #lifeOfPI, read about using const_cast .

Why is a pointer to pointer needed to allocate memory in this function?

I have a segmentation fault in the code below, but after I changed it to pointer to pointer, it is fine. What is the reason?
void memory(int * p, int size) {
try {
p = (int *) malloc(size*sizeof(int));
} catch(exception& e) {
cout << e.what() << endl;
}
}
It does not work in the main function as below:
int *p = 0;
memory(p, 10);
for(int i = 0; i < 10; i++)
p[i] = i;
However, it works like thi .
void memory(int ** p, int size) { `//pointer to pointer`
try {
*p = (int *) malloc(size*sizeof(int));
} catch(exception& e) {
cout<<e.what()<<endl;
}
}
int main()
{
int *p = 0;
memory(&p, 10); // Get the address of the pointer
for(int i = 0; i < 10; i++)
p[i] = i;
for(int i = 0; i < 10; i++)
cout << *(p+i) << " ";
return 0;
}
Because you're wanting to get a pointer value back from the operations done in the function. malloc allocates memory and gives you an address for that memory.
In your first example, you store that address in the local argument variable p, but since it's just the argument, that doesn't make it back to the main program, because C/C++ are pass-by-value by default - even for pointers.
Main Function malloc
p p allocated
+---+ +---+
| 0 | | 0 | A
+---+ +---+
becomes...
p p allocated
+---+ +---+
| 0 | | ------------> A
+---+ +---+
and thus when main reads p, it gets 0, not A.
In your working code, you follow the pointer passed to an address, and that address gives you the location of the pointer variable in the main program. You update the pointer value at that address, which the main program can then look up the value of to use as its memory location - thus passing the address returned by malloc back to the main program for use.
Main Function malloc
p p allocated
+---+ +---+
| 0 |<------- | A
| | | |
+---+ +---+
becomes...
p p allocated
+---+ +---+
| |<------- |
| ----------------------> A
+---+ +---+
and thus when main reads p, it gets A.
A pointer stores the address at which the data is stored. Passing a pointer to a function means giving it the address of the data. However, here you have no address for the data until calling malloc. So instead you need to pass the address of the pointer (i.e. pointer to pointer). This allows memory to take the address of the pointer p and set p to point to the area of memory it allocates for the data.
In C, you have only pass-by-value. So your function memory() gets it own local-only copy of p. malloc inside memory() assigns only to the copy of p that is local to the function. When memory() returns to main(), the copy of p from main is unchanged. In C++, you solve this by using pass-by-reference, like this:
void memory(int*& p, int size)
In C, you use double pointers to achieve similar results.
In your first call to memory:
void memory(int * p, int size)
Realize that you are passing a VALUE to memory(), not an address. Hence, you are passing the value of '0' to memory(). The variable p is just a copy of whatever you pass in... in contains the same value but does NOT point to the same address...
In your second function, you are passing the ADDRESS of your argument... so instead, p points to the address of your variable, instead of just being a copy of your variable.
So, when you call malloc like so:
*p = (int *) malloc(size*sizeof(int));
You are assigning malloc's return to the value of the variable that p points to.
Thus, your pointer is then valid outside of memory().
The first example does not work because the pointer parameter is not the pointer in main, it just holds the same value.
You need a pointer to pointer because you need to return the value of the newly allocated pointer.
There is three ways to return that value (2 if you use C):
use a pointer, here it is a pointer to pointer
use a reference, here it is a reference to pointer
use the return value of the function, so make memory return a int * instead of void
The third way has definitely my preference.
(and not, I won't admit you could also use a global, it's not a fourth way but an horror).
You don’t need to use a pointer to pointer, but a referenced pointer, i.e., a * &, not just *.
Regarding,
memory(p, 10); // Get the address of the pointer
This just sends the p value, not the address of the p. It sends (*p). if the address of p is 123 and its value is 50, it sends 50 to the function.
And at the memory function it makes a new pointer with new address like 124 and it contains 50; and it will allocate the memory and write the start of the allocated memory to 124, not 123, so p at the main still contains 50. So you did nothing! You can control this with this code.
#include <iostream>
#include <conio.h>
#include <exception>
using namespace std;
void memory(int* p, int size) { // *************pointer to pointer` is a must**********
try {
p = new int[size];
p[0] = 100;
} catch(bad_alloc &e) {
cout << e.what() << endl;
}
}
int main()
{
int *p = 0; ******you can do you should do this*******
p = new int;
/* p = malloc(sizeof(int)); // This just changes the value inside
// of p. It is unnecessary.
And you will lose a address from memory :) And possibly it
will be unsafe if you free p may, you just
free one address
*/
/* Before using a pointer, always allocate its memory, else
you'll get frequent system crashes and BSODs */
memory(p, 10); // Get the address of the pointer // You are getting nothing
cout << p[0];
// We set p[0] to 100, but it will write a garbage value here.
// Because the value inside of p didn't change at the memory
// function, we sent just the value inside of p.
getch();
return 0;
}
I corrected the code... read the comments and all will be clear...
#include <iostream>
#include <conio.h>
#include <exception>
using namespace std;
void memory(int* p, int size) { // Pointer to pointer` not needed
try {
p = new int[size];
} catch(bad_alloc &e) {
cout<<e.what()<<endl;
}
}
int main()
{
//int *p = 0; Wrong ... no memory is assigned and then
// you are passing it to a function
int *p;
p = new int; // p = malloc(sizeof(int));
/* Before using a pointer, always allocate its memory, else
you'll get frequent system crashes and BSODs */
memory(p, 10); // Get the address of the pointer
for(int i = 0; i < 10; i++)
p[i] = i;
for(int i = 0 ; i < 10; i++)
cout << *(p+i) << " ";
getch();
return 0;
}