I'm trying to modify a variable by a pointer, the problem is that they have the same address but the output is not right.
Here's the code:
int *ret;
int set = 56;
ret = (int *)&ret - 1;
*ret = 3;
cout << ret << endl << &set << endl << set <<endl;
The output is:
0x61ff08
0x61ff08
3
This look great, but what is really weird is that when I replace:
cout << ret << endl << &set << endl << set <<endl;
With this:
cout << ret << endl << set <<endl;
The output becomes:
0x61ff04
56
The pointer change of value and the set variable isn't modified though. It's like if I take out the &set of the cout the address pointed of the pointer exchange his address with the variable.
If I do this:
ret = (int *)&ret + 1; // instead of -1
The output becomes:
0x61ff0c
3
Can I have an explanation? I didn't find any documentation about this.
Can I have an explanation? I didn't find any documentation about this.
Main documentation in this case is C++ standard, though it is sometimes not to easy to find and comprehend information from there. So short version in your case - you can only subtract or add integers to a pointer when resulting pointer would point to an element in the same array or pointing to the fictitious element behind the last (in this case it is illegal to dereference your pointer). For this purpose single variable is treated like one element array (so for pointer to single variable you can basically only do pointer + 1). All other hacky tries to access variables through magic with pointer arithmetics are illegal and lead to Undefined Behavior.
Details about UB you can find here What exactly do "IB" and "UB" mean?
The answer was that the compiler is giving address by he's own way to the variable/pointers according to the code so the addresses can change, to fix this problem by only using addresses
instead of :ret = (int *)&ret - 1;
we can use :ret = (int *)ret - ((int)(ret - &set));
(i didn't want to use the basic ret = &set because i was trying to do it by manipulation only addresses)
Related
This post is more of a type of confirmation post rather than a particular question.
I read up some answers on this site and other places to clear up my confusion regarding pointers of type, ex- int(*)[size] which are pointers to an array. From what I've understood, there are some basic differences which I concluded on - 1) pointer arithmetic, 2) dereferencing . I wrote up this code to differentiate between int* and int(*)[size].
int arr1[5] {} ;
int (*ptr1) [5] = &arr1 ;
(*ptr1)[3] = 40 ;
cout << ptr1 << endl ;
cout << ptr1[3] << endl;
cout << ptr1 + 3 << endl ;
int arr2[5] {} ;
int* ptr2 = arr2 ;
ptr2[3] = 40 ;
cout << ptr2 << endl ;
cout << ptr2[3] <<endl ;
cout << ptr2 + 3 << endl ;
Output :
On observing the output of arithmetic on int(*)[size] its evident that when we add say i to it , it jumps over a block of 4*size*i memory whereas the int* jumps over a 4*i memory block. Also in int* the expression of the form ptr2[i] is equivalent to *(ptr2+i) but in pointers of type int(*)[size] this is not the case ptr1[i] is equivalent to (ptr1 + i) and to replicate the action of ptr2[i] we have to do (*ptr1)[i] in this case.
Are there anymore significant differences between the pointers of such type and which pointer amongst them should be preferred and why ?
Please correct my analysis if I have gone wrong somewhere .
There are no differences between different kinds of pointers.
If p has the type T*, p + k is the address k * sizeof(T) away from p.
If p is the location of an object that is not an array element (as is the case when you acquire it with &), p[3] and p+3 are both undefined.
(In this case, p[0] is the only well-defined indexing, and p+0 and p+1 are the only well-defined arithmetical expressions – but you're not allowed to dereference p+1.)
Your pointer-to-array code is more similar to this int* version:
int x = 0;
int* ptr2 = &x ;
ptr2[3] = 40 ;
cout << ptr2 << endl ;
cout << ptr2[3] <<endl ;
cout << ptr2 + 3 << endl ;
which you can probably see is Just Wrong.
Are there anymore significant differences between the pointers of such type and which pointer amongst them should be preferred and why ?
Yes, the first snippet with ptr1[3] results in undefined behavior as you're trying to access memory(pointed by ptr1 + 3) that is not meant to be accessed by you.
Note that just the expression ptr1 + 3 is well-defined but if we try to dereference this like *(ptr1 + 3) or ptr1[3] then we will have undefined behavior.
Undefined behavior means anything1 can happen(from C++ standard's perspective) including but not limited to the program giving your expected output. But never rely on the output of a program that has undefined behavior.
On the other hand, ptr2[3] is well-defined.
1For more reading(technical definition of) on undefined behavior you can refer to undefined behavior's documentation which mentions that: there are no restrictions on the behavior of the program.
The author of this code states that (long)tab returns address of the tab. Is it true? If yes, why is it so?
char tab []= "PJC"
cout << " tab = " << tab << ", address: " << (long)tab << "\n" << endl;
Yes, its true. Raw arrays in C/C++ are considered so that their name is the pointer to the first element. So, you can write:
char tab[] = "PJC";
char c = *(tab + 1); // c == J
As pointer is no more than an integer value representing the address in memory, casting pointer to long will print you the address value.
You must be sure that integer would hold all values. Pointers always matches word size, so on 32-bit CPU a pointer is 4 byte, in 64-bit it is 8 byte and you'll need 64-bit integer not to have overflow - what exact type is it depends on the system (may be long long). You can use intptr_t (thanks #Avt) to store pointer values.
Typecasting a variable changes its interpretation, but the actual value remains the same. If you were to print the value with format specifier %x then you'll always get the same result, what typecast you use won't matter.
In this case, tab is a char*, which is nothing but an "address" of the location.
You should cast to void* to get the address. Run following to check
char tab []= "PJC"
cout << " tab = " << tab << ", address1: " << (void*)tab << ", address2: " << (long)tab << "\n" << endl;
But remember that result depends of architecture!
I found this occurrence to be rather interesting, let me explain:
When I initialized a int array, I started to wonder how c++ handles an index with a no initialized value. When directly using cout, c++ directly outputs the values as 0. However, when inserting a for loop right afterwards, with the same purpose it instead points to the values inside the memory location, and pretends they were not initialized.
To regenerate this error, copy & paste the code below onto a compiler. Run it once without the for loop, and once with the for loop.
I am just interested to find out why this occurs.
#include <iostream>
using namespace std;
int main() {
int myArray[4];
myArray[2] = 32;
cout << "\n Val 1: "<< myArray[0] << "\n Val 2: "<< myArray[1]<< "\n Val 3: "<< myArray[2]<< "\n Val 4: "<< myArray[3]<< "\n Val 5: "<< myArray[4];
cout <<"\n ----------------------------";
/*
for(int i = 0; i < 5; i++){
cout << "\n Val " << i << ": " << myArray[i];
}
*/
return 0;
}
You are likely witnessing the work of a (clever) optimizer:
Without the for loop, you access the array elements with a fixed constant, a constant which the optimizer can easily proove will lead to an uninitialized value, which is also never used again. As such, it can optimize away actually reading the element from the uninitialized memory, because it is perfectly entitled to use some constant instead.
With the for loop, you have a second usage of the values (through the use of a dynamic index), and the optimizer has to ensure that the undefined value you read from the array elements in the first cout is the same as the one that is later read within the loop. Obviously, it does not try to unroll the loop - after that it would know how to optimize the reads away.
In any case, whenever you access an uninitialized value, that value is undefined, it can be anything, including zero (even though you are not yet invoking undefined behavior). Whenever you use such a value for memory access (uninitialized pointer etc.), you have undefined behavior at its worst.
This is going to be a long-winded post, so I apologize in advance.. but trying to ask multiple questions with context:
So, I've been trying to learn C++, and I've been picking everything up fairly easily, but I make a habit of trying to do things alongside the tutorials in "slightly different ways", in order to ensure that I understand the functionality of the thing I'm learning.
I seem to have hit a mental roadblock regarding constants and their involvements with pointers.
In the previous section, I think I got a pretty solid grip on references, dereferences (and the difference between * when used for dereferences and pointers), and then wrote this code:
int a[5];
int * p;
p = a;
cout << "Select the value for the first item at address(" << &a[0] << ")" << nl;
cin >> *p;
p++;
cout << "Select the value for the second item at address(" << &a[1] << ")" << nl;
cin >> *p;
p++;
cout << "Select the value for the third item at address(" << &a[2] << ")" << nl;
cin >> *p;
p++;
cout << "Select the value for the fourth item at address(" << &a[3] << ")" << nl;
cin >> *p;
p++;
cout << "Select the value for the fifth item at address(" << &a[4] << ")" << nl;
cin >> *p;
for (int n=0;n<5;n++)
cout << a[n] << "(" << &a[n] << ")" << nl;
Now, I realize that this isn't necessarily the most "optimized" solution, ever.. but it worked, I was able to "write" into the array I had store on the memory, and display the changes. It was neat, and like I said.. I think I got a pretty good understanding of how these things worked.
..and then, I hit the next section, which used the example:
const char * terry = "hello";
to teach me, and I quote: "As in the case of arrays, the compiler allows the special case that we want to initialize the content at which the pointer points with constants at the same moment the pointer is declared" (this being on the cplusplus.com tutorial).
Anyway, to get to the point: in order to try and familiarize myself with it and the previous section, I tried writing:
const char * p = "Hello.";
for (int n=0;n<5;n++)
cout << p[n] << "(" << &p[n] << ")" << nl;
cout << nl;
..and this does not work. I essentially tried replicating my previous code (although without the writing aspect) in an attempt to be able to read the RAM-location of each character in this constant array, and I experimented with every possible combination of pointers, references, dereferences, etc.. but I just get a print out of the whole "Hello." array with &p.
How in the hell does one get the reference of a constant array? I think I understand the basic premise that I'm creating an array and immediately allocating it to memory, and then assigning a pointer (p) to the first block ("H")'s location.. but I can't seem to print the blocks out. I was able to get the location of the first block to print at one point (can't remember what code I used to do this) and tied it into the for loop, but even then.. it just ALWAYS printed the location of the first block, even when assigned to follow the [n] count.
I have no idea what I'm missing, here, or if I'm just trying to reach "over my head", but maybe I just don't understand the usage/point of creating an array without being able to location the memory assignment of each item within it..
This brings me to my next issue, though. How does one get the memory location of a char variable, whether constant or not? I have been having issues with this code, as well:
char const a = 100;
int * b = &a;
cout << a << nl << *b << nl;
cout << nl;
Obviously, this doesn't work.. because I can't assign b to the location of a, since they're different variables.. and obviously making a char pointer is silly, since it's just going to print messed up/null characters instead of the location (I checked this, obviously.. not just assuming).
I hope I'm just missing an option to use which may just be "more advanced" than where I'm currently at.. but if I'm not, I don't quite see the point in being able to access the block location of any type of variable/constant, if you can't access ALL of them due to restrictions of the type being used.
This problem is sorta what limits the third quoted code, too: the fact that I can't just assign a variable to hold the &p value, since it itself would have to be a char to be compatible.. which is pointless since char can't hold the eight-digit reference.
In
const char * p = "Hello.";
[...] cout << &p[n] [...]
&p[n] is a pointer to char, and cout::operator<< has an overload that takes a pointer to a char and prints a null-terminated string, that's probably why you're confused.
I am probably missing something fundamental, but i cannot find a solution to the following issue.
I have a two-dimensional array of some float elements and i am trying to find a way to be able to reference them by using only a single value.
Example:
float test[5][50];
test[3][25] = 34.67;
cout << test[3][25] << endl;
int id = 25;
cout << *test[id*5+3] << endl;
I am hoping to get same result from both cout. Instead my output looks like this:
34.67
Segmentation fault
What am I doing wrong?
Thanks!
Without testing, I think something like this might work. Note that C++ arrays are major->minor from left dimension to right dimension.
float test[5][50];
test[3][25] = 34.67;
cout << test[3][25] << endl;
int id = 25;
float* test2 = &test[0][0]
cout << test2[(3 * 50) + id] << endl;
test is a float[][] with 5 elements (each of which is a float[] with 50 elements), and you are referring to test[128]. Hence the seg fault.You need to convert from single index to subscript using integer division and mod:
cout << test[id/50][id%50] << endl;
You should assert(id/50<5); to make sure your index is within bounds.
The crash is because you are trying to read the contents of the element as a memory address
*test[id*5+3] means int address = test[id*5+3]; then read memory at address.
If that address is 0 or memory you don't own then it will crash.
Accessing a two-dimensional bitmap (image) with a single reference is often useful.
Use:
int image2D[dim2][dim1];
int *image1D = &image2D[0][0];
Now
image2D[i][j] == image1d[i*dim1+j]
I agree with the first comment, that you really shouldn't do it, but I'll answer anyway.
I think that if you try:
cout << test[id*5+3] << endl;
it should work. There is no need to dereference with *.