Having a structure
struct Person{
Person( int i):id(i){};
Person * next;
int id;
};
class Test{
public:
void addList( Person *&f , Person *&l , int i){
Person *tmp = new Person(i);
if( f == nullptr ){
f = tmp;
l = tmp;
return;
}
first -> next = tmp;
last = tmp;
}
void addArr( int *arr , int i ){
arr[index++] = i;
}
void print( ){
for( int i = 0; i < index; i ++)
cout << arr[i] << " ";
cout << endl;
}
Person *first = nullptr;
Person *last = nullptr;
int index = 0;
int *arr = new int[10];
};
function addList add node into linked list and addArr adds element into arr.
My question is about pointer and reference pointer.
in
void addList( Person *&f , Person *&l , int i){
Person *tmp = new Person(i);
if( f == nullptr ){
f = tmp;
l = tmp;
return;
}
first -> next = tmp;
last = tmp;
}
I need to pass pointer as reference. Otherwise , the local copy of pointer would be changed not outer. I assume compilator creates something like
Person *temporary = new Person(*f);
But would I not have to pass array by reference?
I am quite confused by this fact.
But would i do not have to pass array by reference?
Not in this case, by passing your Person pointer by reference in the addList function, you are able to alter the pointer itself. That is like saying, "Pointer, use a different address". This is possible, as it was passed by reference.
Whereas in your addArr function, you are not altering the pointer to the array itself. Rather, you are altering the data that is pointed to. "Pointed to data, use a different value". This data arr is pointing to is the same data outside the scope of the function.
So, no, you don't have to pass the array by reference.
Related
I wrote a simple function which finds the oldest person in an array of structs. The structure stores information about age and name.
#include <iostream>
struct Person
{
int age;
char name[16];
};
char* oldest(Person* arr, int len)
{
int max = 0;
char* ptr = nullptr;
Person elem;
for (int i = 0; i < len; i++)
{
elem = arr[i];
if (max < elem.age)
{
max = elem.age;
ptr = arr[i].name;
}
}
return ptr;
}
int main()
{
Person list[3] = {
{20, "Alice"},
{70, "Bob"},
{25, "James"}
};
std::cout << oldest(list, 3) << '\n';
}
It yields correct result (namely I see Bob on the screen), but when I use elem instead of arr[i] in the line ptr = arr[i].name; (which is nothing but giving another name to arr[i], right??) the program suddenly starts giving some weird results (unprintable characters). I have no idea why it behaves this way.
For your reference, this is the code that doesn't work:
char* oldest(Person* arr, int len)
{
int max = 0;
char* ptr = nullptr;
Person elem;
for (int i = 0; i < len; i++)
{
elem = arr[i];
if (max < elem.age)
{
max = elem.age;
ptr = elem.name;
}
}
return ptr;
}
ptr = elem.name; assigns to ptr the address of the first element of elem.name (because the arary elem.name is automatically converted to a pointer to its first element). elem.name is of course an array inside elem, and elem is an object with automatic storage duration, meaning it is created automatically in the block it is defined in and it is destroyed when execution of that block terminates. So, when the function return, elem ceases to exist in the C++ model of computing, and a pointer to part of it becomes invalid.
… which is nothing but giving another name to arr[i], right??
No, the statement elem = arr[i]; makes a copy of arr[i] in elem. It does not make elem an alternate name for arr[i]. That copy ceases to exist when the function returns.
If you removed the Person elem; declaration and, inside the loop, used Person &elem = arr[i]; instead of elem = arr[i];, that would define elem to be a reference to arr[i]. Then it would be effectively an alternate name for arr[i], and ptr = elem.name; would set ptr to point to the first element of arr[i].name.
(which is nothing but giving another name to arr[i], right??)
Not right. elem is a distinct object. It is not a name of arr[i].
but when I use elem instead of arr[i] in the line ptr = arr[i].name; ... the program suddenly starts giving some weird results
With that change, you are returning a pointer to (a member of) an automatic variable. When the function returns, the automatic variable is destroyed and the returned pointer will be invalid. When you indirect through the invalid pointer and attempt to access deallocated memory, the beahviour of the program is undefined.
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 );
I know I should know this, but it's late and my brain just won't put the pieces together.
This is as straight forward as a question can get:
I have a struct item. I want to create a pointer to an array of pointers to that item type.
Eg.
struct item {
int data;
string moreData;
};
I want to have an ArrayPointer that point's to an array. I want that array to contain in each element a pointer to an item.
How do I do this in C++, or more sepcifically where do I need to put how many dereferencing operators? I know how to declare basic (single indirection) pointers and am pretty fluent in their use.
I need information for the following steps if at all possible:
Declaring the ArrayPointer.
Initializing the ArrayPointer with a size s.
Initializing each element of ArrayPointer with new item.
eg:
for(int i = 0; i < s; i++)
ArrayPointer[i] = // a new item
I feel like as soon as someone posts an answer I'm going to facepalm so hard I break my nose.
If I have understood correctly then you need something like this
item **ArrayPointer = new item *[s];
for ( int i = 0; i < s; i++ )
{
ArrayPointer[i] = new item; { i, "More Data" };
}
Or
item **ArrayPointer = new item *[s];
for ( int i = 0; i < s; i++ )
{
ArrayPointer[i] = new item;
ArrayPointer[i]->data = i;
ArrayPointer[i]->moreData = "More Data";
}
To free the allocated memory you can in reverse order
for ( int i = 0; i < s; i++ )
{
delete ArrayPointer[i];
}
delete [] ArrayPointer;
Otherewise if s is a constant then you may simply declare an array of pointers. For example
item * ArrayPointer[s];
for ( int i = 0; i < s; i++ )
{
ArrayPointer[i]->data = i;
ArrayPointer[i]->moreData = "More Data";
}
file.h
struct item {
int data;
string moreData;
};
item ** array;
file.cpp
array = new item*[s];
for(int i = 0; i < s; i++)
{
array[i] = new item;
array[i]->data = 10;
array[i]->moreData = "data";
}
What you want is an array of struct item *, which are pointers to item structs.
An array of such pointers is a struct item **.
#include <string>
#include <cstdlib>
using namespace std;
struct item {
int data;
string moreData;
};
struct item * newItem(int data, string moreData) {
struct item *result = (struct item *) malloc(sizeof(struct item));
result->data = data;
result->moreData = moreData;
return result;
}
struct item ** array; // We don't know the size of the array in advance.
int main() {
int arraySize = 3; // We get this value from somewhere (user input?).
array = (struct item **) malloc(3*sizeof(struct item *));
// Now the array has been allocated. There is space for
// arraySize pointers.
array[0] = newItem(5, "ant"); // Let's make some items. Note that
array[1] = newItem(90, "bear"); // newItem() returns a pointer to
array[2] = newItem(25, "cat"); // an item.
return 0;
}
So I was trying to convert a BST to DLL using some given functions which I had to use. While doing that, I kept getting segmentation faults. As I tried debugging it, I finally came to this. I have written a very simple test script below.
What I knew about pointers is it is passed by reference, as in if I am changing the value/object to which the passed pointer points to, it is reflected in my original calling function.
Why is it that when I create a new Node and then pass the pointer (myf), it works, but when I just pass the pointer and create the new Node inside the function, it shows segmentation fault (myf2)?
If this is because the new node goes out of scope, check the function "myf" again. I have created a new Node which is pointed to by my original node. And the value of this is retained after the function call ends. Doesn't this too go out of scope then?
I have some basic fundamental problems with pointers it appears and this would really help. Thanks
#include<iostream>
using namespace std;
class Node
{
public:
int val;
Node *left;
};
void myf(Node *a)
{
a->left = new Node();
a->left->val = 20;
a->val = 15;
}
void myf2(Node *a)
{
a = new Node();
a->val = 35;
}
int main()
{
Node *a = NULL, *b = NULL;
a = new Node();
a->val = 5;
myf(a);
cout << "New value of a = " << a->val << endl;
cout << "left value of a = " << a->left->val << endl;
myf2(b);
cout << "New value of b = " << b->val << endl;
}
Your problem is, your pointer isn't being set to b, to do so, you'd need to edit myf2 to something like this:
void myf2(Node **a)
{
*a = new Node();
(*a)->val=35;
}
And call myf2 like so:
myf2(&b);
And that should solve your problem, I believe.
Don't think of Node *b as only a pointer, think of it as an integer as well, because that's what a pointer breaks down to, an integer pointing to a space in memory.
So you pass a pointer of the pointer(an integer) to the function.
Another example would be:
void myfunction(int *i) {
*i = 5;
}
int main(int argc, char** argv) {
int x;
myfunction(&x);
cout << x << endl;
return 0;
}
But that's using an actual integer.
Why is it that when I create a new Node and then pass the pointer (myf), it works,
Node *a:
main() makes it point it to a block of memory, you pass that address to myf, you update the memory in that block. It works!
But when I just pass the pointer and create the new Node inside the function, it shows segmentation fault (myf2)?
Node *b:
main() doesn't assign it anything, it is pointing to NULL, myf2() get just the address that is NULL, you create another pointer b (not the same as that in main() ), make it points to some block of memory, but it doesn't update what your original b in main() points to, which is still pointing to NULL. Hence SEGFAULT.
Essentially you are trying two different valid approaches, this is the right way:
Case 1.
main()
{
Node* a = NULL;
a = new Node(); //make 'a' point to some valid block of memory
myf(a); // here you are passing the address of the memory block of type Node
cout << "New value of a = " << a->val << endl; //and this is valid since 'a' points to a valid address
}
void myf(Node *a)
{
a->left = new Node();
a->left->val = 20; // Since the address that you got here is valid, you can make changes here, and in main() Node* a is aware of this address
a->val = 15;
}
Case 2.
main()
{
Node* b = NULL;
myf2(&b); // here since b points to NULL, you have to send the address where this NULL is stored so that the called functon can upadte this NULL to something meaningful
cout << "New value of b = " << b->val << endl; // this is correct, because we changed what 'b' pointed to from NULL to a valid block of memory of type 'Node'
}
void myf2(Node **a) //It is a double pointer here because you need to update what it points to, curently it holds NULL
{
*a = new Node(); // Make it point to a valid address, remember main() has track of 'a',
*a->val = 35; // Now if you make any changes to the blok that 'a' points to, main() will have account of it
}
You need to return the reference of Node *a to which you have dynamically allocated memory..
Node* myf(Node *a)
{
a->left = new Node();
a->left->val=20;
a->val=15;
return a;
}
In main ()
a = myf(a);
previously a in main() is not pointing to memory allocated in myf() function...
Receive your Node ptr by reference as below..
void myf2(Node *&a) //<-- Notice & in function signature.
In your current code, you are passing a (Node*) by value, so, whatever changes done in the function will not reflect outside of function and accessing b->val (null ptr access) will be a segment fault
#include<iostream>
using namespace std;
struct data {
int x;
data *ptr;
};
int main() {
int i = 0;
while( i >=3 ) {
data *pointer = new data; // pointer points to the address of data
pointer->ptr = pointer; // ptr contains the address of pointer
i++;
}
system("pause");
}
Let us assume after iterating 3 times :
ptr had address = 100 after first loop
ptr had address = 200 after second loop
ptr had address = 300 after third loop
Now the questions are :
Do all the three addresses that were being assigned to ptr exist in the memory after the program gets out of the loop ?
If yes , what is the method to access these addresses after i get out of the loop ?
Well the memory is reserved but you have no pointer to the memory so that's whats called a memory leak (reserved memory but no way to get to it). You may want to have an array of data* to save these pointers so you can delete them when you are done with them or use them later.
For starters, there will be no memory allocated for any ptr with the code you have.
int i = 0;
while( i >= 3)
This will not enter the while loop at all.
However, if you are looking to access the ptr contained inside the struct then you can try this. I am not sure what you are trying to achieve by assigning the ptr with its own struct object address. The program below will print the value of x and the address assigned to ptr.
#include<iostream>
using namespace std;
struct data {
int x;
data *ptr;
};
int main() {
int i = 0;
data pointer[4];
while( i <=3 ) {
pointer[i].x = i;
pointer[i].ptr = &pointer[i];
i++;
}
for( int i = 0; i <= 3; i++ )
{
cout<< pointer[i].x << endl;
cout<< pointer[i].ptr << endl;
}
}
OUTPUT:
0
0xbf834e98
1
0xbf834ea0
2
0xbf834ea8
3
0xbf834eb0
Personally, when I know the number of iterations I want to do, I choose for loops and I use while only when I am looking to iterate unknown number of times before a logical expression is satisfied.
I cannot guess what you are trying to achieve...
But Me thinks, you are trying to achieve similar to this....
But, If you want to make linked list using your implementation, you can try this...
#include<iostream.h>
struct data {
int x;
data *ptr;
data()
{
x = -1;
ptr = NULL;
}
};
data *head = new data();
data *pointer = head;
int main() {
int i = 0;
while( i <=3 ) {
data *pointer = new data();
pointer->x = /*YOUR DATA*/;
::pointer->ptr = pointer;
::pointer = pointer;
i++;
}
i=0;
data* pointer = head->next;
while( i <=3 ) {
cout<<pointer->x;
pointer = pointer->ptr;
i++;
}
system("pause");
}
This will print , the elements in the linked list;