Basic C++ String Pointers - c++

Why it is not throwing a error in line 2?
char *p = "Hello";
p = "Bye";
*p is the variable so p is the address of the variable *p.
Please someone explain me what is the case in above code?

*p is not "the variable". p is the variable and it is a pointer. C and C++ have the odd looking declaration syntax in which you declare a variable with the same kind of syntax used to access the variable.
char *p;
In that declaration we are declaring p, not *p but declaring p to be the thing p would need to be for *p to be a char
char *p = "Hello";
Now it may be even another step less intuitive, because the thing on the right of the = is the initial value for p not the initial value for *p. That is how C and C++ work and is easy to get used to and understand, even if the meanings of the left and right side of that initially seem counter-intuitive.
So your example:
char *p = "Hello";
p = "Bye";
I can see why someone who doesn't know C or C++ might think there is a different level of indirection to the use of p on the first line vs. the second. But actually on both lines p is a pointer and the address of a text literal is being stored in that pointer.

Those are not C++ String Pointers, those are C-Strings. It is not throwing a error because a string-literal is itself a pointer to the first element. p is the pointer, *p is the first element of you String

Here is a example
int firstvalue = 5, secondvalue = 15;
int * p1, * p2;
p1 = &firstvalue; // p1 = address of firstvalue
p2 = &secondvalue; // p2 = address of secondvalue
*p1 = 10; // value pointed to by p1 = 10
*p2 = *p1; // value pointed to by p2 = value pointed to by p1
p1 = p2; // p1 = p2 (value of pointer is copied)
*p1 = 20; // value pointed to by p1 = 20
cout << "firstvalue is " << firstvalue << '\n';
cout << "secondvalue is " << secondvalue << '\n';
return 0;
}
The problem you have is p is the variable with its pointer.

In the first case, p is assigned the address of the string. In the second case, p is reassigned the address of another string
EDIT - String literals are not allocated in the stack. Thanks to Q

Related

Setting a variable equal to a variable that is equal to nullptr

I have an array called my_array of linked lists.
Node* x = my_array[0];
if (head == nullptr)
{
my_array[0] = new Node;
}
How come this one works fine, but
Node* x = my_array[0];
if (head == nullptr)
{
x = new Node;
}
how come this one leaks memory? Aren't they pointing to the same thing? They should be the same, right?
You misunderstood how pointers work. Pointers are variables like any other and their value is a memory address. Nothing more and nothing less.
This line:
Node* x = my_array[0];
Copies the address from my_array[0] to a new variable called x. While the address is the same, the x and my_array[0] are not the same thing. They are two distinct variables holding the same address.
This line:
my_array[0] = new Node;
Re-assigns the address of my_array[0] to a new address of the heap allocated Node object. It overwrites the old address in my_array[0] and thus leaks the memory because the address (and the object in it) was never freed. However you still have it in x so you can still free it and prevent the leak.
This line:
x = new Node;
does essentially the same thing but overwrites the address stored in x instead. This might be fine though because the original address is still in my_array[0] (remember x was just copy of that address) and might be freed later. And also you can still free the new address in x as well too. So the second one might not leak either.
I highly recommend you to watch POINTERS by TheCherno. It is excellent and simple explanation.
x is a variable on its own and it is not an alias for my_array[0]. Changing x only affects the value of x.
Example:
int zero = 0;
int one = 1;
int* arr[] = {&zero};
int* x = arr[0];
x = &one;
std::cout << "*arr[0] = " << *arr[0] << '\n'
<< "*x = " << *x;
Output:
*arr[0] = 0
*x = 1
As you can see, what x points to is changed but the array is not affected. Now, if you want an alias, you should use a reference:
int* arr[] = {&zero};
int*& x = arr[0];
x = &one; // note the &
std::cout << "*arr[0] = " << *arr[0] << '\n'
<< "*x = " << *x;
Output:
*arr[0] = 1
*x = 1
Meaning you should use Node *&x = my_array[0]; or with modern C++, auto& x = my_array[0];.

Dereferencing a pointer gives an address

i have this code snippets
const int col= 5;const int row= 5;
int a[row][col] = {0};
int (*p)[col] ;
p = a;
And these statements print the same address
cout <<p;
cout << endl;
cout << *p;
in my opinion since p points to an array of 5 ints, dereferencing it
should give the first value which doesn't seem to be the case.
help!
since p points to an array of 5 ints
That much is correct.
dereferencing it should give the first value
No, it's type is "pointer to array"; dereferencing that gives "array", which decays to an int* pointer when you do just about anything with it - including printing it.
If you had a pointer to int
int * p = a;
then *p would indeed give the first array element.

Beginner C++ programmer, confused over dynamic arrays

I am trying to create a class analogous to the built-in vector class in C++. I have tried to follow all the instructions in Walter Savitche's textbook, but just can't get it to work properly.
The code was written using the Code::Blocks IDE and compiled using the gcc compiler.
The thing I think I'm missing is the relationship between array parameters and a pointer that points to an array.
This is what I understand about normal variables:
int *p1, *p2, *p3, *p4, a;
a = 5; // variable of type int with value 5
p1 = &a; // p1 now points to the value 5
p2 = p1; // p2 now also points to the value of a
p3 = new int; // p3 points to an anonamous variable of type int with undefined value
*p3 = *p1 // value of variable changed to the value of a, namely 5, but doesn't point to a
p4 = new int; // p4 points to an anonamous variable of type int with undefined value
*p4 = 5; // value of variable changed to 5
p4 = p1 // p4 now also points to the value of a
This is what I essentially don't understand about arrays and pointers that point to arrays
int *p1, *p2, *p3, *p4, a[3] = {4, 5, 6}; // a points to the first indexed element of the array, namely 4
p1 = a; // p1 points to the exactly the same thing as a
p2 = new int[3]; // p2 points to an array of base type int with undefined values
p2[0] = 8; // is this the correct usage? is p2 "dereferenced"
p2[1] = 9;
p2[2] = 10;
p2[2] = p1[2]; // again is this correct? is the third element of the array pointed to by p2 now equal to 6?
*p3 = a // what does this mean?
p4 = new int[4]; // p4 points to an array of base type int with undefined values
p4[0] = p2[0];
p4[1] = p2[1];
p4[2] = p2[2];
p4[3] = 3
p2 = p4 // p2 now points to p4, but what happens to the array p2 was pointing to?
delete [] p2; // does this destroy the pointer and the array it is pointing to or just one or the other?
For completeness sake my class is defined as follows:
class VectorDouble
{
public:
// constructors
VectorDouble(); // default constructor
VectorDouble(int init_count); // user specified
VectorDouble(const VectorDouble& vd_object); // copy constructor
// destructor
~VectorDouble();
// accessors
int capacity_vd(); // get max_count
int size_vd(); // get amt_count
double value_at(int index); // get value of "value" at index i
// mutators
void push_back_vd(double put_at_end); // insert new element at end of "value"
void reserve_vd(int incr_capacity); // set max_count
void resize_vd(int incr_size); // set amt_count
void change_value_at(double d, int index); // set value of "value" at index i
// overloaded =
void operator =(const VectorDouble& vd_object_rhs);
// other
friend bool operator ==(VectorDouble vd_object1, VectorDouble vd_object2);
private:
double *value; // pointer that points to array of type double
int max_count; // the memory allocated to the array
int amt_count; // the amount of memory in use
};
And the troublesome function is:
void VectorDouble::push_back_vd(double put_at_end)
{
double *temp;
if(amt_count == max_count)
max_count += 1;
temp = new double[max_count];
for(int i = 0; i < amt_count; i++)
temp[i] = value[i];
amt_count += 1;
temp[amt_count] = put_at_end;
value = temp;
}
The member function just seems to insert 0.0 instead of the user input, I have no idea why...
In main:
VectorDouble vec1(10);
double dd;
cout << "Enter 3 doubles to vec1:\n";
for(int i = 0; i < 3; i++)
{
cout << i << ": ";
cin >> dd;
vec1.push_back_vd(dd);
}
cout << "The variables you entered were:\n";
for(int i = 0; i < 3; i++)
cout << i << ": " << vec1.value_at(i) << endl;
I enter:
12.5
16.8
15.2
I get back:
0
0
0
I fixed it! Only problem is that the mistake was exceedinly simple. Sorry to waste everybodies time, but thanks to all, I did learn quite a lot!
The mistake was my placement of amt_count += 1;, I'm used to arrays indexed from 1 not zero (I have done a lot of coding in the R language). The corrected code with the memoery leak taken care of is:
void VectorDouble::push_back_vd(double put_at_end)
{
double *temp;
if(amt_count == max_count)
max_count += 1;
temp = new double[max_count];
for(int i = 0; i < amt_count; i++)
temp[i] = value[i];
temp[amt_count] = put_at_end;
amt_count += 1;
delete [] value;
value = temp;
}
This is what I understand about normal variables
All correct, with the caveat that I'd avoid the terminology "points to the value x"; you're pointing to the object, which in turn has value x.
This is what I essentially don't understand about arrays and pointers that point to arrays
You're confusing pointers with arrays. In int a[3], a is an array. It is not a pointer. It is an array.
*p3 = a isn't valid, so it means nothing.
p2 now points to p4, but what happens to the array p2 was pointing to?
You've leaked it.
// does this destroy the pointer and the array it is pointing to or just one or the other?
It destroys the thing you new'd, that the pointer is pointing to. i.e. the array
Otherwise all correct.
As for your vector implementation, the main problem is that temp[amt_count] is an overflow because you've already incremented amt_count. Also, vector implementations typically grow exponentially rather than on-demand. Finally, you're leaking the previous storage.
Using different terminology might help you:
A pointer is just an ordinary variable. Instead of holding an integer, a float, a double, etc., it holds a memory address. Consider the following:
int* p = nullptr; // p has the value "nullptr" or null memory address
int i = 5; // i has value 5
p = &i; // p now has the value of the address of i
The ampersand gets the address of a variable.
An asterisk dereferences a pointer; that is it will get the value stored in the memory address the pointer holds:
cout << *p << endl; // Prints whatever is stored in the memory address of i; 5
As for your vector implementation, try moving this line amt_count += 1; to below this line:
temp[amt_count] = put_at_end;, as you're trying to access beyond the end of your array.
Most of your understanding is correct. But...
a[3] = {4, 5, 6}; // a points to the first indexed element of the array, namely 4
Although arrays and pointers can be indexed and treated in a similar fashion, they are different, and their differences can lead to some sneaky bugs; so be careful with this statement.
*p3 = a // what does this mean?
This is invalid. Your types don't match: *p3 is an integer, a is an array.
p2 = p4 // p2 now points to p4, but what happens to the array p2 was pointing to?
The array p2 was pointing to is now leaked memory. This is bad.
delete [] p2; // does this destroy the pointer and the array it is pointing to or just one or the other?
The value of the pointer does not change. However, the memory it points to is deallocated, so dereferencing it will give you undefined results. It's best to set p2 = nullptr; after deleting it.
This answer might help with your understanding of arrays and accessing their elements.
"p2 now points to p4, but what happens to the array p2 was pointing to?"
It is 'leaked', this means its still allocated but there is no way to reach it anymore. If you keep doing this is the same program your memory size will keep growing
Other languages (Java, c#,...) have 'garbage collectors' that detect when this happens and will free the memory automatically
C++ solution to this problem is to never user naked arrays and pointers. Instead you use std::vector and std::shared_ptr; these will clean up for you
Your function is really wrong...
void VectorDouble::push_back_vd(double put_at_end)
{
double *temp;
if(amt_count == max_count)
max_count += 1;
temp = new double[max_count];
for(int i = 0; i < amt_count; i++)
temp[i] = value[i];
amt_count += 1;
temp[amt_count] = put_at_end;
value = temp;
}
Notice that in each call you allocate new array (even if there's still space), copy everything in it and leak memory (old array)...
Here is a slightly corrected version, but it's not guaranteed to be completely OK (;
void VectorDouble::push_back_vd(double put_at_end)
{
if(amt_count == max_count)
{
max_count += 1;
double *temp = new double[max_count];
for(int i = 0; i < amt_count; i++)
temp[i] = value[i];
delete[] value;
value = temp;
}
value[amt_count] = put_at_end;
amt_count += 1;
}

How does this operation on pointers work?

int x = 4;
int* q = &x; // Is it always equivalent to int *q = &x; ?
cout << "q = " << q << endl; // output: q = 0xbfdded70
int i = *q; // A
int j = *(int*)q; // B, when is this necessary?
cout << "i = " << i << endl; // output: i = 4
cout << "j = " << j << endl; // output: j = 4
My question is what does lines A and B do, and why the outputs are both 4?
It is a basic usage of pointers, in A you dereference pointer (access the variable to which a pointer points)":
int i = *q; // A
while B is doing exactly the same but it additionally casts pointer to the same type. You could write it like that:
int j = *q; // B
there is no need for (int*)
int x = 4;
x is 4
int* q = &x;
q is the memory location of x (which holds 4)
cout << "q = " << q << endl; // output: q = 0xbfdded70
There's your memory location.
int i = *q; // A
i is the value at memory location q
int j = *(int*)q; // B
j is the value at memory location q. q is being cast to an int pointer, but that's what it already is.
int i = *q; // A
Dereferences a pointer to get the pointed value
int j = *(int*)q; // B
type casts the pointer to an int * and then dereferences it.
Both are same because the pointer is already pointing to an int. So typecasting to int * in second case is not needed at all.
Further derefenecing yields the pointed integer variable value in both cases.
Lines A and B are equivelent as q is already an int* and therefor (int*)q equals q.
int i = *q; yelds that i becomes the value of the integer pointed to by q. If you want to make i to be equal to the adress itself remove the asterisk.
A: Dereference - takes a pointer to a value (variable or object) and returns the value
B: Cast to int* and than dereference
The result is the same because the pointer is already to int. That's it.
Line A takes the value that q points to and assigns it to i. Line b casts q to the type int* (which is q's type already, so that cast is entirely redundant/pointless), then takes the value that q points to and assigns it to j.
Both give you 4 because that's the value that q points to.
Line A de-reference pointer q typed as int *, i.e. a pointer points to an int value.
Line B cast q as (int *) before de-reference, so line B is the same as int j = *q;.

How to convert int* to int

Given a pointer to int, how can I obtain the actual int?
I don't know if this is possible or not, but can someone please advise me?
Use the * on pointers to get the variable pointed (dereferencing).
int val = 42;
int* pVal = &val;
int k = *pVal; // k == 42
If your pointer points to an array, then dereferencing will give you the first element of the array.
If you want the "value" of the pointer, that is the actual memory address the pointer contains, then cast it (but it's generally not a good idea) :
int pValValue = reinterpret_cast<int>( pVal );
If you need to get the value pointed-to by the pointer, then that's not conversion. You simply dereference the pointer and pull out the data:
int* p = get_int_ptr();
int val = *p;
But if you really need to convert the pointer to an int, then you need to cast. If you think this is what you want, think again. It's probably not. If you wrote code that requires this construct, then you need to think about a redesign, because this is patently unsafe. Nevertheless:
int* p = get_int_ptr();
int val = reinterpret_cast<int>(p);
I'm not 100% sure if I understand what you want:
int a=5; // a holds 5
int* ptr_a = &a; // pointing to variable a (that is holding 5)
int b = *ptr_a; // means: declare an int b and set b's
// value to the value that is held by the cell ptr_a points to
int ptr_v = (int)ptr_a; // means: take the contents of ptr_a (i.e. an adress) and
// interpret it as an integer
Hope this helps.
use the dereference operator * e.g
void do_something(int *j) {
int k = *j; //assign the value j is pointing to , to k
...
}
You should differentiate strictly what you want: cast or dereference?
int x = 5;
int* p = &x; // pointer points to a location.
int a = *p; // dereference, a == 5
int b = (int)p; //cast, b == ...some big number, which is the memory location where x is stored.
You can still assign int directly to a pointer, just don't dereference it unless you really know what you're doing.
int* p = (int*) 5;
int a = *p; // crash/segfault, you are not authorized to read that mem location.
int b = (int)p; // now b==5
You can do without the explicit casts (int), (int*), but you will most likely get compiler warnings.
Use * to dereference the pointer:
int* pointer = ...//initialize the pointer with a valid address
int value = *pointer; //either read the value at that address
*pointer = value;//or write the new value
int Array[10];
int *ptr6 = &Array[6];
int *ptr0 = &Array[0];
uintptr_t int_adress_6 = reinterpret_cast<uintptr_t> (ptr6);
uintptr_t int_adress_0 = reinterpret_cast<uintptr_t> (ptr0);
cout << "difference of casted addrs = " << int_adress_6 - int_adress_0 << endl; //24 bits
cout << "difference in integer = " << ptr6 - ptr0 << endl; //6