How to assign constant address to pointer at c++? - c++

I want to check how pointer address will be changed when I'm increasing/decreasing pointer value.
My code is:
void pointers_plus_minus()
{
char *c = (char *) 0x7fff80ccd35c;
int *i = (int *) 0x7fff80ccd35c;
c++;
i++;
cout << "char pointer" << c << endl;
cout << "int pointer" << i << endl;
}
But this code gives me Segmentation fault (core dumped).
I understand that something wrong with address, but it's not clear what. How to fix it? I'm using 64bit Ubuntu.

You can't operate on pointers like they are integers (well, not outside well-defined contexts).
You're only allowed to do c++ and i++ if the pointers point inside an array which you own.
Oops, I think this is actually well-defined because 1 element is treated as an array of 1, and you're allowed to go past the end of an array by one element. Reading from that pointer is still undefined though.
Regardless, although undefined, the crash is probably because cout << c attempts to print out a string, not a pointer. Cast it to void*:
cout << "char pointer" << static_cast<void*>(c) << endl;
Although this will satisfy your curiosity, which is good, it's still undefined and shouldn't do it.

You asked how to assign a constant address to a pointer, but doing so (a) is horrendously non-portable, and (b) doesn't necessarily serve your purpose, which is to see the effect of incrementing a pointer.
Here's a program that may satisfy your curiosity without possibly blowing up due to undefined behavior:
#include <iostream>
int main() {
const int len = 10;
char char_array[len];
int int_array[len];
char *cp = char_array;
for (int i = 0; i <= len; i ++) {
std::cout << "cp = " << static_cast<void*>(cp) << "\n";
cp ++;
}
std::cout << '\n';
int *ip = int_array;
for (int i = 0; i <= len; i ++) {
std::cout << "ip = " << static_cast<void*>(ip) << "\n";
ip ++;
}
}
The output on my (64-bit) system is:
cp = 0x7fffaa5ddc30
cp = 0x7fffaa5ddc31
cp = 0x7fffaa5ddc32
cp = 0x7fffaa5ddc33
cp = 0x7fffaa5ddc34
cp = 0x7fffaa5ddc35
cp = 0x7fffaa5ddc36
cp = 0x7fffaa5ddc37
cp = 0x7fffaa5ddc38
cp = 0x7fffaa5ddc39
cp = 0x7fffaa5ddc3a
ip = 0x7fffaa5ddc00
ip = 0x7fffaa5ddc04
ip = 0x7fffaa5ddc08
ip = 0x7fffaa5ddc0c
ip = 0x7fffaa5ddc10
ip = 0x7fffaa5ddc14
ip = 0x7fffaa5ddc18
ip = 0x7fffaa5ddc1c
ip = 0x7fffaa5ddc20
ip = 0x7fffaa5ddc24
ip = 0x7fffaa5ddc28
Some notes on this:
The pointer increments are valid because each pointer points to an element of an array of the proper type, or just past the end of it, at all times. (You're allowed to construct a pointer just past the end of an array; you're not allowed to dereference such a pointer.)
The output produced when print a pointer of type void* is implementation-defined. On my system, it happens to be a hexadecimal representation of the pointer value, interpreted as if it were an integer -- which is probably the most common way it's done.
You can see that the char* pointer appears to be incremented by 1 each time, and the int* pointer by 4. On my system (and probably yours), pointers are stored as byte addresses. Pointer arithmetic is defined in units of the pointed-to type, not in terms of bytes. Incrementing an int* pointer causes it to point to a memory location sizeof (int) bytes after the previous location -- in this case, 4 bytes. All pointer arithmetic is defined this way; ptr2 - ptr1 gives you the number of elements (of whatever type ptr1 and ptr2 point to) between the two addresses.
The specific values printed tell you something about how memory addresses are managed on your system. The mapping between pointers and integers will generally reflect the system's memory model. That model is largely implementation-specific.

Seg faults, my favorite error messages next to stack overflows, are when you've tried to write to an illegal memory space. That said, how can you guarantee that when your program has been loaded into memory that your stack/heap space falls within the area you are trying to reserve, and more so why would you even want to do this? This is something that can probably be done in Assembly since you have much lower access to the hardware, but I seriously doubt it can be done (or should be done if you can) in C.

Related

Pointer to array in c++

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.

Calculating the number of elements in an array using pointer arithmetic

I have come across a piece of example code that uses pointers and a simple subtraction to calculate the number of items in an array using C++.
I have run the code and it works but when I do the math on paper I get a different answer.
There explanation does not really show why this works and I was hoping someone could explain this too me.
#include <iostream>
using namespace std;
int main() {
int array[10] = {0, 9, 1, 8, 2, 7, 3, 6, 4, 5};
int stretch = *(&array + 1) - array;
cout << "Array is consists of: " << stretch << " numbers" << endl;
cout << "Hence, Length of Array is: " << stretch;
return 0;
}
From: https://www.educba.com/c-plus-plus-length-of-array/
When I run the code I get the number 10.
When I print the results of *(&array + 1) and array by
cout << *(&array+1) << endl; cout << array << endl;
I get of course two hex address's.
When I subtract these hex numbers I get 1C or 28???
Is it possible that C++ does not actually give the hex results or their translation to decimal but rather sees these numbers as addresses and therefore only returns the number of address slots remaining?
That is the closest I can come to an explanation if some one with more knowledge than I could explain this I would be very grateful.
Let's take one step back and take it step-by-step to see if it will help. Continuing from my comment, the problem you are having difficulty with is one of type.
Let's take the array iteself:
int array[10] = {0, 9, 1, 8, 2, 7, 3, 6, 4, 5};
On access, an array is converted to a pointer to the first element in the array (e.g. the address of the first element) subject to caveats not relevant here. So when you say array, you have type int *, a pointer to the first element in array.
Now what happens when I take the address of the array? (&array in)
int stretch = *(&array + 1) - array;
When you take the address of the array, the result is the same address as array, but has type int (*)[10] (a pointer-to-array-of int[10]). When you add 1 to that pointer (recall type controls pointer arithmetic), you get the address for the pointer to the next array of int[10] in memory after array -- which will be 10 int after the first element of array.
So *(&array + 1) gives you the address to the next array of int[10] after array, and then dereference is only needed for type compatibility. When you dereference an int (*)[10] you are left with int[10] -- which on access gives you the address of the first element of that array (one after the original)
Think through the types and let me know if you have further questions.
You forgot a small detail of how pointer addition or subtraction works. Let's start with a simple example.
int *p;
This is pointing to some integer. If, with your C++ compiler, ints are four bytes long:
++p;
This does not increment the actual pointer value by 1, but by 4. The pointer is now pointing to the next int. If you look at the actual pointer value, in hexadecimal, it will increase by 4, not 1.
Pointer subtraction works the same way:
int *a;
int *b;
// ...
size_t c=b-a;
If the difference in the hexadecimal values of a and b is 12, the result of this subtraction will not be 12, but 3.
When I subtract these hex numbers I get 1C or 28 ???
There must've been a mistake with your subtraction. Your result should be 0x28, or 40 (most likely you asked your debugger or compiler to do the subtraction, you got the result in hexadecimal and assumed that it was decimal instead). That would be the ten ints you were looking for.
I will try it with 5 items
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
int array[] {1,2,3,4,5};
int items= sizeof(array)/sizeof(array[0]);
cout << items << endl;
int items2 = *(&array +1) - array;
cout << items2 << endl;
cout << array << endl;
cout << *(&array +1) << endl;
return 0;
}
root#localhost:~/Source/c++# g++ arraySize.cpp
root#localhost:~/Source/c++# ./a.out
5
5
0x7fe2ec2800
0x7fe2ec2814
using https://www.gigacalculator.com/calculators/hexadecimal-calculator.php to subtract the numbers from each other
I get
14 hex
20 decimal.
that fits with the 4 bytes to an integer.
thanx guys :)
this is an edit done on the 12th of december melbourne time ::
I have still had questions on this topic and something did not fit right with me about the entire route to counting array items via this code.
I found something I think is interesting and again would love to know why ( I shall try to explain it as best I can my self anyway)
*(&array + 1) is the question.
lets have a look at it.
as arrays are at there very nature in c and c++ only pointers to the first element in the array how can this work.
I shall use a small set of cout calls to see if I can find out whats happening.
#include <iostream>
using namespace std;
int main(int argc, char* argv[]){
int array[] {1,2,3,4,5,6,7,8,9,10};
int size {0};
size = *(&array + 1) - array;
cout << "size = *(&array + 1) - array = " << size << endl;
cout << "*(&array + 1) = " << *(&array + 1) << endl;
cout << "(&array + 1) = " << (&array + 1) << endl;
cout << "(array + 1) = " << (array + 1) << endl;
cout << "&array = " << &array << endl;
cout << "array = " << array << endl;
cout << "*(&array) = " << *(&array) << endl;
cout << "*(array) = " << *(array) << endl;
cout << "*array = " << *array << endl;
return 0;
}
again this is off proot in my phone so still under root with no systemd.
root#localhost:~/Source/c++# g++ arrayPointerSize.cpp
root#localhost:~/Source/c++# ./a.out
size = *(&array + 1) - array = 10
*(&array + 1) = 0x7ff6a51798
(&array + 1) = 0x7ff6a51798
(array + 1) = 0x7ff6a51774
&array = 0x7ff6a51770
array = 0x7ff6a51770
*(&array) = 0x7ff6a51770
*(array) = 1
*array = 1
we see that as a pointer array can be called with * too derefernce the pointer and give the variable held in position [0] in the array.
when calling &array or reference too array we get the return of the address at the first position in the array or [0].
when calling just array we also get the address for the first position in the array or [0].
when calling *array the * is working as it does for pointers and it is dereferencing the arrays first position [0] to give the variable.
now things get a little interesting.
*(array) also dereferences the array as is seen by its value being given as 1 in this instance.
yet *(&array) does not dereference the array and returns the address to the first position in the array.
in this instance memory address 0x7ff6a51770 is the first spot in the array array = 0x7ff6a51770
and &array (reference to the pointer of the position in memory that is the first spot in the array) gives the same address 0x7ff6a51770.
it is also of note in this instance to remind us of the fact that *(&array) is also returning the first possition in the array and *(array) is not
so we can not dereference a pointer too a position in memory as its variable is the position in memory.
if array and &array give the same answer as array is a pointer too the memory position in the first spot in our array and a reference to
this pointer.
why the different answer for (array + 1) and (&array + 1).
we get the memory address 0x7ff6a51774 for (array + 1) which is in line with an integer taking four bytes on my linux or
the addition of four bytes in memory past the first spot in the array (second array spot) but (&array + 1) gives a different answer.
if we follow the bytes and the code we see that (&array + 1) actually gives us the memory address four bytes after the end of the array.
so pointer too memory address add one gives the amount of bytes the variable type is past the memory address for the start of the array
and the reference to the pointer too the memory address add one gives the address the amount of bytes the variable type is after the last ?? spot in the array.
how then can array and &array return the same answer if (array + 1) and (&array + 1) do not.
it seems to me that the & reference when working with arrays overloads the + operator when doing arithmatic.
this would explain the difference in answers as straight &array has no operator too overload so returns the same answer as calling for
straight array
this small peice of code also shows that the use of pointers using *(&array + 1) is a very bad way to show a way to find array size with
pointers as really arrays are pointers and *(&array + 1) and (&array + 1) give the same result.
the heavy work was really being done by the reference operator &.
I may still be missing something here as I have used cout directly with the different experssions and being a stream it may
be limited in its ability to take advantage of what the reference operator is really doing when working with arrays.
I am still learning this language but I shall for sure keep this in mind as I dive deaper into c++.
I believe other than a few other trials with variables that the true answer will be found when reading the source for GCC g++.
I am not ready for that yet.

c++ pointer and variable address switch of value, why?

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)

Extra number while looping through an array in C++

I am trying to loop through an array of integers using pointers using the following code:
#include <iostream>
int main (int argc, char ** argv)
{
int ar[] = {1,1,2,3,5,8,13,21,34,55};
char s[] = "string";
std::cout << "Print fibonacci until ten using pointers" << std::endl;
for (int * p = ar; *p; p++)
{
std::cout << *p << std::endl;
}
// for (char * cp = s; *cp; cp++)
// std::cout << "char is " << *cp << std::endl;
return 0;
}
On running this code, I get all 10 elements plus a number, 4196368.
But on uncommenting the second for-loop and running it again, the numbers vanishes.
Can someone explain why this happens? If needed, the code is compiled in a 64-bit Linux box.
You're lucky the loop stopped at all; you could have blown up your entire neighbourhood!
Your loop expects to find a "zero" to terminate the array iteration, but your array doesn't have one. Thus, your loop will just keep incrementing past the end of the array until god knows what. The practical results depend on too many practical factors to be either predictable or usefully explained.
I presume that this is an exercise, because using "null-termination" to iterate over an int array is mighty peculiar. In reality you'd just write:
for (auto x : ar)
std::cout << x << '\n';
}
You are invoking an undefined behavior.
The first for loop's termination condition is *p. So it is trying to access memory past what actually is owned by ar. Your loop then runs until it finds a memory location that contains 0 (read false) before terminating. In your case, it ran just one extra time (lucky you!). At my end, it ran four more times before terminating.
You must loop only as many times as the size of the array, which is sizeof(ar)/sizeof(ar[0])
Ensure that you have terminated zero:
int ar[] = {1,1,2,3,5,8,13,21,34,55, 0};
Well, actually this will result in a different outcome on a different machine or a different condition. The one that causes this is your for statement
for (int * p = ar; *p; p++)
{
std::cout << *p << std::endl;
}
Here, you used *p as a conditional for your for loop to keep running. As we know, C++ treat number > 0 as a true and 0 as a false. While in the for statement, your program checks the next memory address if the value in that address is zero or not (True or False). And as you know, the value of the next address in this particular case on your particular PC is 4196368. So the for loop keeps going until the value of the next address is zero. You can see this with printing the address.
for (int * p = ar; *p; p++)
{
std::cout << *p << " " << p << std::endl;
}
You will know here that your code check the next address to see its value an if it is indeed not zero, it will continue the loop.

Cout Not Printing Contents of Pointed To Memory

I have the following code:
if (myFile.is_open()) {
int i = 0;
while (myFile.good()) {
char *ptr = &(reinterpret_cast<char*>(&mem[0]))[i];
myFile.read(ptr, sizeof(struct req));
cout << ptr << endl;
i += sizeof(struct req);
}
}
The cout in the loop here seems to print nothing, although I know that the code is definitely setting the memory because it prints out the correct values if I do something like cout << mem[5] instead. Basically, I just want to print the contents of whatever ptr is referring to. This is probably a silly question, but anyone know what's wrong here?
cout << ptr, if ptr is of type char*, treats ptr as a pointer to (the first character of) a C-style string, and it prints the contents of that string up to, but not including, the terminating '\0' null character.
If you want to print the pointer value, convert to void*:
cout << (void*)ptr << ...
That's assuming you actuallly want to print the value of the pointer, which will probably appear as a hexadecimal memory address. Your title says "Contents of Pointer", which would be the memory address (the contents of the pointer object itself). If instead you want to print the data that the pointer points to, please update your question to make it clearer just what you want to print and in what format.
cout << ptr will print ptr as if it pointed to a C string. Thus, if it hits a NUL character, it will stop. For example, if you try cout << "hello\0world", you will only see hello appear.
Consider writing a hexdump of the memory region instead if you want to see its contents.