Need help understanding output of a pointer exercise - c++

Hi i'm studying a book and there is a question that displays this code:
What is the output of the following code?
int main()
{
int x;
int *p;
int *q;
p = new int[10];
q = p;
*p = 4;
for(int j = 0; j<10; j++)
{
x = *p;
p++;
*p = x+j;
}
for(int k= 0; k<10; k++)
{
cout << *q << " ";
q++;
}
cout << endl;
return 0;
}
I know the output is:
4 4 5 7 10 14 19 25 32 40
but i cannot understand why, i know p = q and since the first p in the array of 10 equals 4 so does q but after that shouldnt it just increment by one each time since j is?

p++ increment the pointer so it points to the next element. This is known as pointer arithmetic. This is not affecting the value. For that, you need to dereference the pointer using * as in *p = x+j
*p = x+j; sets the value pointed to by p to x+j. x = value pointed to previous p(before increment) and j goes from 0 to 9. So it gives:
4+0(4), 4+1(5), 5+2(7), 7+3(10), ...
Since it initialize first element to 4 and start writing at second element, that is why you have two 4s at the beginning.
However, I think the loop should be
for(int j = 0; j<9; j++)
{
x = *p;
p++;
*p = x+j;
}
else there will be out of bound access to p.

Related

Can't Access some values in an array using a pointer

So I was asked to write a program which uses a pointer that points to the first element in an array and pass the pointer to a function. Then using only pointer variables (and looping constructs), print only the array values that are exact multiples of 7. Here's the script:
#include <iostream>
using namespace std;
void print_sevens(int *nums,int length){
for(int i = 0; i < length; i++){
nums = nums + i;
if(*nums % 7 == 0)
cout << *nums << endl;
}
}
int main() {
int a[5]={7,49,2,8,70};
int *p1 = &a[0];
print_sevens(p1,5);
}
The output from this is :
7
49
-149462114
I can't find out what is wrong. Any help is appreciated. Thanks
nums is the pointer to the start of the array. You are reassigning it at every loop iteration to be nums + i, not nums + 1. So, at the fourth iteration, for example, nums points to the initial array start + 0 + 1 + 2 + 3, which is the seventh element in your array of 5 elements. That's why you get garbage.
Use a subscript to make your life easy:
for(int i = 0; i < length; i++){
if(nums[i] % 7 == 0)
cout << nums[i] << endl;
}

Flipping an array using pointers

#include <iostream>
using namespace std;
int* flipArray(int input[], int n)
{
int output[n];
int pos = 0;
for (int i = n-1; i >= 0; i--)
{
output[pos++] = input[i];
}
int* p = output;
for (int k = 0; k < n; k++)
cout << *p-k << endl << endl;
return p;
}
int main()
{
const int SIZE = 5;
int firstArray[SIZE];
for (int n = 0; n < SIZE; n++)
{
firstArray[n] = n+1;
}
int* a;
a = flipArray(firstArray, SIZE);
for (int j = 0; j < SIZE; j++)
cout << *a-j << endl;
cout << endl;
cout << *a << '\t' << *a+1 << '\t' << *a+2;
return 0;
}
I am attempting to flip firstArray using a function that returns a pointer, but I am struggling to understand how accessing an index using a pointer works.
Here is why I am confused:
Within the function flipArray, the following for-loop:
for (int k = 0; k < n; k++)
cout << *p-k << ' ';
prints "5 4 3 2 1" to the console. It was my understanding that I should be accessing an element of a vector with *(p+k), not *(p-k). If I print *(p+k), "5 6 7 8 9" is printed to the console. If I print the array without pointers and using k as the index location, "5 4 3 2 1" is printed to the console.
Within my main function, however, the values of *a which is assigned pointer p from the flipArray function, I do not get the same results:
for (int j = 0; j < SIZE; j++)
cout << *a-j << endl;
prints 5
0
-1
-2
-3 to the console, and
for (int j = 0; j < SIZE; j++)
cout << *a+j << endl;
prints 5
2
3
4
5 to the console.
Further, I thought that the pointer location of *p and the pointer of location of *a should be the same! But when I print the address &p in the function, I get the location of 0x28fde0, and when I print the address of &a in the main, I get the location 0x28fedc. Of course, these were done during the same run.
Could someone tell me where I have gone astray? Thanks!
Thanks to everyone for the informative answers.
I have updated my solution, and it is now returning what I would expect it to. I have a new question about memory leaks and when pointers need to be deleted.
int* flipArray(int input[], int n)
{
int* output = new int[n];
int pos = 0;
for (int i = n-1; i >= 0; i--)
output[pos++] = input[i];
return output;
}
int main()
{
const int SIZE = 5;
int firstArray[SIZE];
for (int n = 0; n < SIZE; n++)
{
firstArray[n] = n+1;
}
int* a;
a = flipArray(firstArray, SIZE);
for (int j = 0; j < SIZE; j++)
cout << a[j] << " "; // can also be written as *(a+j), which is more prone to bugs
delete [] a;
return 0;
}
Will the pointer output be deleted when the function flipArray returns? If not, how should I delete output while also returning it? Is deleting the pointer a in my main function the same thing as deleting output, because they point to the same location?
It has been pointed out that your main problem is coming from the operator precedence. The * operator in *p - k is evaluated before the -. This means that k will be subtracted from the value of the int pointed at by p.
This is a huge pain, which is why the braces pointer[k] are commonly used. There are situations where using pointer arithmetic *(pointer + k) makes more sense, but it can be a source of bugs.
One point to note here: it is always better to use parenthesis even if you are not sure whether or not you need them.
You do have a second problem:
Here you are declaring output on the stack as a local variable, then you are returning output. When you return back to the previous stack frame, this pointer will be pointing to a decallocated buffer:
int* flipArray(int input[], int n)
{
int output[n]; // allocated on the stack
int pos = 0;
for (int i = n-1; i >= 0; i--)
{
output[pos++] = input[i];
}
int* p = output;
for (int k = 0; k < n; k++)
cout << *p-k << endl << endl;
return p; // this stack frame ends.
}
This means the contents of the buffer can be overwritten if the space the buffer is using is reallocated. Use new to allocate on the heap:
int* output = new int[n];
make sure to call delete on the pointer when you are done using it.
This bug can even present security vulnerabilities in your applications, so make sure you know when to allocate on the heap in C++.
Update:
Question: When this function returns, the array still exists in memory, and it's location is stored in the pointer a. Does returning the value output delete it? If not, will deleting the pointer a when I am done with it in the main function serve the same purpose?
When you delete the pointer, the memory pointed to that pointer is deallocated and the pointer is left dangling. A reference to a deleted pointer is pointing at memory that is technically free, which is bad. If the allocator library decides that it wants to reuse that space, your buffer, which is now in free space, will be reallocated. This means your buffer will lose all data integrity and the data inside of it cannot be trusted.
A common practice is to assign pointers to NULL when you are done using them. This way your program will crash and you will know where your bug is:
int* p = new int[10];
...
delete p;
p = NULL;
...
p[0] = 0; // this will now crash because you are accessing NULL.
for (int k = 0; k < n; k++)
cout << *p-k ;
It was my understanding that I should be accessing an element of a vector with *(p+k), not *(p-k).
Your understanding is right.You are not accessing the array here.p points to the first element 5 and every time k is substracted from it, which gives you 5-0 5-1 5-2 and so on which is equivalent to the filpped array.So if you want to access the array using the pointer
for (int k = 0; k < n; k++)
cout << *(p+k) ;// Note the paranthesis
for (int k = 0; k < n; k++)
cout << *p-k << endl << endl;
What this code is doing is completely different from what you think it does.
*p - k will be processed like
*p = 5 - 0 = 5
*p = 5 - 1 = 4
and so on not *(p+k) or *(p-k)
For your understanding :
int a[5] = { 1,2,6,4,5};
In order to access 3rd element in the array you do
a[2] = *(a+2)
and not
*a + 2
*(a + 2) = 6 and *a + 2 = 1 + 2 = 3
Take care of not returning the pointer to the local variable which will lead to undefined behavior

How to add array data and display them in c++?

I am using following code in c++
#include <iostream>
using namespace std;
int functionIs();
int main()
{
functionIs();
return 0;
}
int functionIs()
{
int value[3];
value[0] = 0;
for (int i = 0; i < 3; i++)
{
value[i] += i + 1;
}
for (int k = 0; k < 3; k++)
{
cout << "Value = " << value[k];
cout << endl;
}
return 0;
}
Output:
Value = 1
Value = 2
Value = 4197152
What is wrong?
Thank you in advance.
You need to assign a value to every element in array value. You are only giving the first element the value 0:
Value[0] = 0;
If not you add to whatever was in memory at location value[i] whit this code:
Value[i] += i + 1;
I think you are trying to add one to the previous value in the array, not add i+1 to each value in the array. Try changing the first loop to:
value[0]=0;
for (int i=1; i<3; i++) {
value[i] = value[i-1]+1;
}
Accessing uninitialised variables is undefined, as already stated in comments. The easiest to initialise all the elements of an array to zero would be
int value[3] = {};
Aside: When i going to be changing for every iteration and the element assigned is going to change every time, why use +=, you can just assign = and be done with it.

pointer arithmetic in C++ using char*

I'm having trouble understanding what the difference between these two code snippets is:
// out is of type char* of size N*D
// N, D are of type int
for (int i=0; i!=N; i++){
if (i % 1000 == 0){
std::cout << "i=" << i << std::endl;
}
for (int j=0; j!=D; j++) {
out[i*D + j] = 5;
}
}
This code runs fine, even for very big data sets (N=100000, D=30000). From what I understand about pointer arithmetic, this should give the same result:
for (int i=0; i!=N; i++){
if (i % 1000 == 0){
std::cout << "i=" << i << std::endl;
}
char* out2 = &out[i*D];
for (int j=0; j!=D; j++) {
out2[j] = 5;
}
}
However, the latter does not work (it freezes at index 143886 - I think it segfaults, but I'm not 100% sure as I'm not used to developing on windows) for a very big data set and I'm afraid I'm missing something obvious about how pointer arithmetic works. Could it be related to advancing char*?
EDIT: We have now established that the problem was an overflow of the index (i.e. (i*D + j) >= 2^32), so using uint64_t instead of int32_t fixed the problem. What's still unclear to me is why the first above case would run through, while the other one segfaults.
N * D is 3e9; that doesn't fit in a 32 bit int.
When using N as size of array, why use int?
does a negative value of an array has any logical meaning?
what do you mean "doesn't work"?
just think of pointers as addresses in memory and not as 'objects'.
char*
void*
int*
are all pointers to memory addresses, and so are exactly the same, when are defined or passes into a function.
char * a;
int* b = (char*)a;
void* c = (void*)b;
a == b == c;
The difference is that when accessing a, a[i], the value that is retrieved is the next sizeof(*a) bytes from the address a.
And when using ++ to advance a pointer the address that the pointer is set to is advanced by
sizeof(pointer_type) bytes.
Example:
char* a = 1;
a++;
a is now 2.
((int*)a)++;
a is now 6.
Another thing:
char* a = 10;
char* b = a + 10;
&(a[10]) == b
because in the end
a[10] == *((char*)(a + 10))
so there should not be a problem with array sizes in your example, because the two examples are the same.
EDIT
Now note that there is not a negative memory address so accessing an array with a signed negative value will convert the value to positive.
int a = -5;
char* data;
data[a] == data[MAX_INT - 5]
For that reason it might be that (when using sign values as array sizes!) your two examples will actually not get the same result.
Version 1
for (int i=0; i!=N; i++) // i starts at 0 and increments until N. Note: If you ever skip N, it will loop forever. You should do < N or <= N instead
{
if (i % 1000 == 0) // if i is a multiple of 1000
{
std::cout << "i=" << i << std::endl; // print i
}
for (int j=0; j!=D; j++) // same as with i, only j is going to D (same problem, should be < or <=)
{
out[i*D + j] = 5; // this is a way of faking a 2D array by making a large 1D array and doing the math yourself to offset the placement
}
}
Version 2
for (int i=0; i!=N; i++) // same as before
{
if (i % 1000 == 0) // same as before
{
std::cout << "i=" << i << std::endl; // same as before
}
char* out2 = &out[i*D]; // store the location of out[i*D]
for (int j=0; j!=D; j++)
{
out2[j] = 5; // set out[i*D+j] = 5;
}
}
They are doing the same thing, but if out is not large enough, they will both behave in an undefined manner (and likely crash).

Understanding the use of pointers

Hi I' have come across to a code that I have hard time to understand why it is working and I would appreciate if someone could explain me
Here is the code This is actually a very simplified version of the real code which can be found here http://acts.nersc.gov/hypre/example10/ex10.cxx.html
#include <iostream>
int main(int argc, char *argv[]){
double ***elemStiff = new double**[10];
int i, k;
for (i = 0; i < 10; i++){
elemStiff[i] = new double*[4];
for (k = 0; k < 4; k++){
elemStiff[i][k] = new double[4];
}
double **A = elemStiff[i];
for (k = 0; k < 4; k++)
A[k][k] = 2/3.;
A[0][1] = A[1][0] = -1/6.;
A[0][2] = A[2][0] = -1/3.;
A[0][3] = A[3][0] = -1/6.;
A[1][2] = A[2][1] = -1/6.;
A[1][3] = A[3][1] = -1/3.;
A[2][3] = A[3][2] = -1/6.;
}
std::cout << elemStiff[1][0][0] << std::endl;
}
In short, here we initialize and fill the values of the elemStiff array which has 10 rows and each row is a 4x4 matrix.
What is very weird to me is that the code fills in the entries of elemStiff array with the help of the double **A = elemStiff[i];
When I first saw I though it would give an error but it works!. The values passed on A, they are passed at the same time on elemStiff array, but I dont understand why it works
Thank you
Let's start with simpler version:
int* array = new int[10];
int* ptr = array; // equivalent to ptr = &array[0]
for (int i = 0; i < 10; ++i)
ptr[i] = i; // writing into the memory that ptr points to
for (int i = 0; i < 10; ++i)
std::cout << array[i]; // outputs: 0123456789
In this example we create a pointer ptr that points to the first element of array. Then when we are writing into the memory that ptr points to, we are actually writing into that array. So then when we check values of array elements, we can see they were properly initialized.
Your code is pretty much the same, there's just an array of 10 two-dimensional arrays:
double ***elemStiff = new double**[10];
And then just like we used ptr in my simple example, you use a temporary pointer A to make it point to each of those 10 two-dimensional arrays:
for (i = 0; i < 10; i++)
double **A = elemStiff[i];