how typecasting & dereferencing works here? - c++11

#include<stdio.h>
int main(){
int a, b, c;
char *p = 0;
int *q = 0;
double *r = 0;
cout<<(int)(p + 1); // printing 1 char size
cout<<(int)(q + 1); // printing 4
cout<<(int)(r + 1); // printing 8
int y = 9;
int *u = &y;
cout<<(int)(u+1); //printing 7208688
cout<<*(p+1); //not able to dereferance
}
How is type-casting working in both the above case?
Why pointers p, q, r are unable to dereference?

Dereferencing any of p, q, r, p + 1, q + 1, r + 1 or u + 1 has undefined behaviour, because none of those pointers point to objects of the correct type.
You can add to a pointer, to get a different pointer value. This is only defined for results that stay within the same array, plus the "one-past-the-end" pointer value (treating a pointer to a single object as an array of length one). You can also convert a pointer to an integer type, to get an implementation defined value. Doing those things does not involve dereferencing the pointer.
Adding to a null pointer is also undefined behaviour, because the null pointer does not point to an object, there is nothing to be "one-past-the-end" of.

Related

assign pointer to constant pointer in c++

I have a constant pointer cp that points to A and a non constant pointer p that points to B. I wold say that I can assign cp to p, i.e. p=cp because in this way both cp and p point to A and I cannot do the opposite: cp=p, because in this way I am saying that cp should point to B but cp is a constant pointer so I cannot change what it is pointing to.
I tried with this simple code but the result is the opposite, can someone explain me what is the correct version please?
std::vector<int> v;
v.push_back(0);
auto cp = v.cbegin(); // .cbegin() is constant
auto p = v.begin(); // .begin() is non constant
now if I write cp=p the compiler doesn't mark as error, but if I write p=cp the compiler marks the error.
cbegin is a pointer to something that is constant. You can change that pointer to point to something of the same constant type.
You're confusing this with a pointer, which is constant, to something that is not.
This is hard to see here, but the difference is between
const int* cp; // pointer to a constant value, but can point to something else
int* const pc; // pointer is constant, value can change
const int* const cpc; // pointer cannot be changed, value it points to cannot be changed
You can never make a "pointer that points to something that's not const" point at something that is const – because that means that you could change what is const, by derefencing the pointer!
const int value = 5; // can never change value
const int value2 = 10; // can never change value
const int* cp = &value; // our pointer to const int points at a const int
*cp = 6; // error: the value of something const can't be changed
cp = &value2; // fine, because we're pointing at a const int
int* p const = &value; // error: trying to point a pointer to non-const to a const, which would allow us to:
*p = 7; // which should be illegal.

I want to know why the results are different in these two ways

func main() {
var a int = 10
var b int = 20
swap(&a,&b)
fmt.Println(a,b)
var c int = 10
var d int = 20
swap2(&c,&d)
fmt.Println(c,d)
}
func swap(x, y *int) {
*x = *y
*y = *x
}
func swap2(x, y *int) {
*x,*y= *y,*x
}
//I want to know why the results are different in these two ways
//20 20
//20 10
The reason why swap2(&c,&d) results in different values being set to c and d is because this function consists of a single assignment statement while swap(&a,&b) consists of two assignment statements. Assignment statements have a particular evaluation order in go. From the language specifications:
The assignment proceeds in two phases. First, the operands of index expressions and pointer indirections (including implicit pointer indirections in selectors) on the left and the expressions on the right are all evaluated in the usual order. Second, the assignments are carried out in left-to-right order.
With this in mind, let's annotate swap(x, y *int):
// x points to an int with value 10,
// y points to an int with value 20.
*x = *y // 1.
*y = *x // 2.
The first assignment statement occurs first, so do that:
// x points to an int with value 10,
// y points to an int with value 20.
*x = *y // 1. (value of int pointed to by x) = (value of int pointed to by y)
// Now x points to an int with value 20.
*y = *x // 2.
After the first assignment statement finishes, the second assignment statement is run:
// x points to an int with value 10,
// y points to an int with value 20.
*x = *y // 1. (value of int pointed to by x) = (value of int pointed to by y)
// Now x points to an int with value 20.
*y = *x // 2. (value of int pointed to by y) = (value of int pointed to by x)
// Now y points to an int with value 20.
However, because swap2 uses only a single assignment statement, we have to be careful about what happens in what order. The specifications say that the pointer indirections on the left and the expressions on the right are evaluated at the same time:
// x points to an int with value 10
// y points to an int with value 20
*x,*y = *y,*x
// 1. (value of int pointed to by x), (value of int pointed to by y) = 20, 10
Second, the assignments are carried out in left-to-right order. But because we have already evaluated the right-hand side of the statement, those are just values.
// x points to an int with value 10
// y points to an int with value 20
*x,*y = *y,*x
// 1. (value of int pointed to by x), (value of int pointed to by y) = 20, 10
// 2. Now x points to an int with value 20, y points to an int with value 10
Put another way, swap2 does the same thing as this function:
swap3(x, y *int) {
valueX := *x
valueY := *y
*x = valueY
*y = valueX
}
The advantage of the form of swap2 is that the function does not explicitly allocate unnecessary temporary variables.

2-D array and pointer to 2-D array

int main()
{
int arr[][3]={{1,2},{3,4},{4,5}};
int (*p)[3];
p=arr;
cout<<sizeof(p)<<" "<<sizeof(*p);
return 0;
}
Above is my code,the output of this code is 4 12.So my doubt is what do the complier interpret p and *p as ? what they are actually pointing to?
P is a pointer, you probably have a 32-bit system, therefore sizeof(p) returns 4.
Then you defined p as a pointer to an array of 3 ints, the sizeof int is 4, so the sizeof what it's pointing to, sizeof(*p) is 12.

why the difference between two pointers pointing to different elements of an array is the no of elements between these two pointers?

int main()
{
int arr[]={2,3,5,6,8};
int *ptr;
ptr=&arr[3];
cout<<ptr-arr;
}
Q.why the answer is 3 after compiling the code i.e. as it should be 3*sizeof(int) which in this case should be 3*4=12?
When you subtract pointers you get the distance between them, not the allocated size. The same goes for iterators in STL.
https://en.cppreference.com/w/cpp/language/operator_arithmetic#Additive_operators
The reason is that it is much easier to write correct code.
When the pointer difference between consecutive elements of an array is 1, then you can use ++p to walk through the array (assuming p is a pointer to an element). For example:
int a[10];
for (auto p = a, e = a + 10; p != e; ++p)
*p = 42;
Notice how the code does not have to deal with the size of the elements. If the array type changes from int to double, the code does not have to change and is still correct.

why rvalue reference can be bind to a non reference type

int main()
{
int rx = 0;
int ry = std::move(rx); //here is the point of my question
int lx = 0;
int ly = &lx; //(2) obviously doesn't compile
std::cin.ignore();
}
I'm a little bit lost with this aspect of rvalue, I can't understand how we can't bind &&rx to ry, because std::move(rx) is a reference to a rvalue, so I believed that this kind of expression could only be bind to a reference type as is it he case for lvalue reference and illustrated in (2)
References != address-of operator.
int& ly = lx; // reference
int* ly = &lx; // pointer
std::move obtains an rvalue reference to its argument and converts it to an xvalue. [1]
Which in turn can be copied to ry.
The expression int ry = std::move(rx); does not "bind" rx to ry. It tells the compiler that rx is no longer needed and that its contents can be moved to ry while at the same time invalidating rx.
This is especially useful when functions return by value:
std::vector<int> foo() {
std::vector<int> v = {1,2,3,4};
return v;
}
std::vector<int> u = foo();
At return v the compiler notice that v is no longer needed an that it can actually use it directly as u without doing a deep copy of the vector contents.

Resources