C++ pointer offset gets squared - c++

I have a data type called 'tod', with which I create arrays. To iterate between elements of this type inside function (with pointer), I want to use an offset. However, this offset gets squared during operation:
tod theTime[] = { {12,0,0, "noon"}, {0,0,0, "midnight"}, {11,30,0, "lunch time"}, {18,45,0, "supper time"}, {23,59,59, "bed time"} };
auto tsize = sizeof(tod);
auto p1 = &theTime[0];
auto p2 = &theTime[0] + tsize;
cout << "size of tod = " << tsize << endl;
cout << "p1 = " << p1 << endl;
cout << "p2 = " << p2 << endl;
That gives me:
size of tod = 44
p1 = 0x7ffd3e3b0bf0
p2 = 0x7ffd3e3b1380
The difference between the two hex values comes down to 0x790, which is 1936 (decimal) and 44^2. How is this happening? Someone please help.

You're misunderstanding about pointer arithmetic:
If the pointer P points to the ith element of an array, then the expressions P+n, n+P, and P-n are pointers of the same type that point to the i+nth, i+nth, and i-nth element of the same array, respectively.
e.g. &theTime[0] + 1 will return the pointer pointing to the 2nd element of the array theTime; then &theTime[0] + tsize will try to return the pointer pointing to the tsize + 1th element (note it's getting out of the bound and leads to UB). That's why you got 1936, i.e. 44 * 44.

Related

Why can I not increment the value of an int variable by using "++" when working with pointers?

I am trying to increment the value of an element inside an array, using a pointer storing that element's address.
When I write it as " p++; " it does not work, whereas if I write it as *p=*p+1 it works.
*p=*p+1; // this increments the value
*p++; //while this does not
I am expecting both ways to work
operator ++ has higher precedence than dereference so *p++ increments the pointer and then performs dereference. If you want to increment the value it initially points to then you need to add parentheses: (*p)++;
#include <iostream>
using namespace std;
int main (int argc, char *argv[])
{
int numbers[] = { 100, 200, 300, 400, 500, 600 };
int *p1 = &numbers[0];
int *p2 = &numbers[2];
int *p3 = &numbers[4];
*p1 = *p1 + 1;
*p2 = *p2++;
++*p3;
cout << numbers[0] << " " << numbers[1] << " " << numbers[2] << " " << numbers[3] << " " << numbers[4] << " " << numbers[5];
}
Running this through Xcode gives me a clue as to what's going wrong, it says: "temp/test.cxx:11:12: warning: unsequenced modification and access to 'p2' [-Wunsequenced]".
The output is 101 200 300 300 501 600.
The first method works, as you said in your question.
The second does something completely different from what you were expecting: it takes the value pointed to by p2 (300) then increments the pointer and saves the value back to that new address.
The third example with p3 is closer to what you're trying to achieve I think.

Assigning an address of an array to a variable and delete

My assignment wants me to do this: "Allocate an array of seven ints; initialize it to 1,2,4,8, etc...; and assign its address to a variable p2"
This was my code:
int* p2 = new int[7] {1,2,4,8,16,32,64};
cout << "Drill 3 & 4 (allocating 7 element array): " << endl;
for (int i = 0; i < 7; ++i) {
cout << p2[i];
}
but I am concerned that I am misunderstanding the instructions. Because of that, I tried this code I found online:
int* sev = new int[7];
for (int i = 0; i<7; ++i)
sev[i] = i+1;
int* p2 = sev;
cout << "p2= " << p2 << ", *p2=" << *p2 << endl;
cout << "sev= " << sev << ", *sev=" << *sev << endl;
But it outputs the address and then 1. And when I add a for loop to do it seven times for all of the elements, it's just 1111111.
Is my code above assigning the address to the pointer or doing something different?
I later have to make it equal to p1, which is a pointer (*int p1 = &x, x = 7 <--not code, for reference). And I need to deallocate p1 and p2 (and p3, but that's not relevant). It lets me deallocate p2, but not p1. So, I am thinking maybe I am not understanding the question or am not approaching it correctly.
Both the variable sev and the variable p2 are pointing to the first element of the data you have allocated. That's really all you have.
So when you dereference the pointers (with e.g. *sev) you dereference the pointer to that element only, and get that value only.
A more "graphical" way of looking at your "array" might be like this:
+--------+--------+--------+--------+--------+--------+--------+
| sev[0] | sev[1] | sev[2] | sev[3] | sev[4] | sev[5] | sev[6] |
+--------+--------+--------+--------+--------+--------+--------+
^
|
sev / p2
The arrow points to the first element only.

Why is this method for navigating through an array wrong?

I'm trying to understand C pointers, I set up the following example:
int main()
{
int temp[] = {45,67,99};
int* address;
address = &temp[0]; //equivalent to address = temp;
std::cout << "element 0: " << *address << std::endl;
address = (address + sizeof(int));
std::cout << "element 1: " << *address << std::endl;
std::getchar();
return 0;
}
Now, the first element is printed correctly while the second one is garbage. I know that I can just use:
address = (address + 1);
in order to move the pointer to the second element of the array, but I don't understand why the first method is wrong.
The operator sizeof returns the size of the object in bytes. So (depending on your compiler) you may have just done
address + sizeof(int) == address + 4
This will obviously access out of bounds when you dereference the pointer. The problem is that the way you are trying to use sizeof is already accounted for in the pointer arithmetic. When you add an integral (e.g. 1) to an int* it already knows to move 1 int over to the next address.
Incrementing a pointer by N will not increment it by N bytes, but by N * sizeof(pointed_type) bytes.
So when you do:
address = (address + sizeof(int));
You are incrementing the address by (probably) 4 times the size of int, which is past your original array.
What you intended to do is:
address = reinterpret_cast<int*>(reinterpret_cast<char*>(address) + sizeof(int));
Which is pretty horrendous.
An array is a group of elements of the Same Type mapped consecutively in memory one-next to the other.
The size of the array is:
sizeof(any element) * the number of elements
So the vice-vers to get the number of elements of an array you can:
Number of elements = sizeof(array) / sizeof(any element).
These elements are addressable and each one is addressed with the first byte's address.
int a[] = {1, 10, 100, 1000, 10000};
std::cout << sizeof(int) << std::endl; // 4
std::cout << sizeof(a) << std::endl; // 20: 5 * 4
The addresses:
cout << &a[0] << " : " << &a[1] << " : " <<
&a[2] << " : " << &a[3] << endl;
The outPut:
0018FF38 : 0018FF3C : 0018FF40 : 0018FF44
As you can see the address is incrementing by sizeof(int) // 4
To do it on your way:
for(int* tmp = array; tmp <= a + nElement; tmp++)
cout << tmp << " : ";
The result:
0018FF38 : 0018FF3C : 0018FF40 : 0018FF44
As you can see the result is identical.
To move from one element to another just increment / decrement the address as I did above:
tmp++; // incrementing the address by 1 means moving to the next element, element means an integer which means 4 bytes. 1 here is not a single byte but a unit or element which is 4 byte here;
To move to the n-element just:
tmp += n;
In your example:
address = (address + sizeof(int)); :
address = address + 4; // moving to the 0 + 4 element which means fifth element (here outbound).

Comparison Of Pointers

I want to compare the memory address and pointer value of p, p + 1, q , and q + 1.
I want to understand, what the following values actually mean. I can't quite wrap my head around whats going on.
When I run the code:
I get an answer of 00EFF680 for everytime I compare the adresss p with another pointer.
I get an answer of 00EFF670 for everytime I compare the address of q with another pointer.
I get an answer of 15726208 when I look at the pointer value of p.
And I get an answer of 15726212 When I look at the pointer value of p + 1.
I get an answer of 15726192 when I look at the pointer value of q
And I get an answer of 15726200 Wehn I look at the pointer value of q + 1.
Code
#include <iostream>
#include <string>
using namespace std;
int main()
{
int val = 20;
double valD = 20;
int *p = &val;
double *q;
q = &valD;
cout << "Memory Address" << endl;
cout << p == p + 1;
cout << endl;
cout << q == q + 1;
cout << endl;
cout << p == q;
cout << endl;
cout << q == p;
cout << endl;
cout << p == q + 1;
cout << endl;
cout << q == p + 1;
cout << endl;
cout << "Now Compare Pointer Value" << endl;
cout << (unsigned long)(p) << endl;
cout << (unsigned long) (p + 1) << endl;
cout << (unsigned long)(q) << endl;
cout << (unsigned long) (q + 1) << endl;
cout <<"--------" << endl;
return 0;
}
There are a few warnings and/or errors.
The first is that overloaded operator << has higher precedence than the comparison operator (on clang++ -Woverloaded-shift-op-parentheses is the flag).
The second is that there is a comparison of distinct pointer types ('int *' and 'double *').
For the former, parentheses must be placed around the comparison to allow for the comparison to take precedence. For the latter, the pointers should be cast to a type that allows for safe comparison (e.g., size_t).
For instance on line 20, the following would work nicely.
cout << ((size_t) p == (size_t) (q + 1));
As for lines 25-28, this is standard pointer arithmetic. See the explanation here.
As to your question:
I want to compare p, p +1 , q , and q + 1. And Understand what the results mean.
If p is at address 0x80000000 then p+1 is at address 0x80000000 + sizeof(*p). If *p is int then this is 0x80000000 + 0x8 = 0x80000008. And the same reasoning applies for q.
So if you do p == p + 1 then compiler will first do the additon: p+1 then comparison, so you will have 0x80000000 == 0x80000008 which results in false.
Now to your code:
cout << p == p + 1;
is actually equivalent to:
(cout << p) == p + 1;
and that is because << has higher precedence than ==. Actually you should get a compilation error for this.
Another thing is comparision of pointers of non related types like double* with int*, without cast it should not compile.
In C and C++ pointer arithmetic is very closely tied with array manipulation. The goal is that
int array[3] = { 1, 10, 100 };
int *ptr = { 1, 10, 100 };
std::cout << array[2] << '\n';
std::cout << *(ptr + 2) << '\n';
outputs two 100s. This allows the language to treat arrays and pointers as equivalent - that's not the same thing as "the same" or "equal", see the C FAQ for clarification.
This means that the language allows:
int array[3] = { 1, 10, 100 };
int *ptr = { 1, 10, 100 };
And then
std::cout << (void*)array << ", " << (void*)&array[0] << '\n';
outputs the address of the first element twice, the first array behaves like a pointer.
std::cout << (void*)(array + 1) << ", " << (void*)&array[1] << '\n';
prints the address of the second element of array, again array behaving like a pointer in the first case.
std::cout << ptr[2] << ", " << *(ptr + 2) << '\n';
prints element #3 of ptr (100) twice, here ptr is behaving like an array in the first use,
std::cout << (void*)ptr << ", " << (void*)&ptr[0] << '\n';
prints the value of ptr twice, again ptr behaving like an array in the second use,
But this can catch people unaware.
const char* h = "hello"; // h points to the character 'h'.
std::cout << (void*)h << ", " << (void*)(h+1);
This prints the value of h and then a value one higher. But this is purely because the type of h is a pointer to a one-byte-sized data type.
h + 1;
is
h + (sizeof(*h)*1);
If we write:
const char* hp = "hello";
short int* sip = { 1 };
int* ip = { 1 };
std::cout << (void*)hp << ", " << (void*)(hp + 1) << "\n";
std::cout << (void*)sip << ", " << (void*)(sip + 1) << "\n";
std::cout << (void*)ip << ", " << (void*)(ip + 1) << "\n";
The first line of output will show two values 1 byte (sizeof char) apart, the second two values will be 2 bytes (sizeof short int) apart and the last will be four bytes (sizeof int) apart.
The << operator invokes
template<typename T>
std::ostream& operator << (std::ostream& stream, const T& instance);
The operator itself has very high precedence, higher than == so what you are actually writing is:
(std::cout << p) == p + 1
what you need to write is
std::cout << (p == p + 1)
this is going to print 0 (the result of int(false)) if the values are different and 1 (the result of int(true)) if the values are the same.
Perhaps a picture will help (For a 64bit machine)
p is a 64bit pointer to a 32bit (4byte) int. The green pointer p takes up 8 bytes. The data pointed to by p, the yellow int val takes up 4 bytes. Adding 1 to p goes to the address just after the 4th byte of val.
Similar for pointer q, which points to a 64bit (8byte) double. Adding 1 to q goes to the address just after the 8th byte of valD.
If you want to print the value of a pointer, you can cast it to void *, for example:
cout << static_cast<void*>(p) << endl;
A void* is a pointer of indefinite type. C code uses it often to point to arbitrary data whose type isn’t known at compile time; C++ normally uses a class hierarchy for that. Here, though, it means: treat this pointer as nothing but a memory location.
Adding an integer to a pointer gets you another pointer, so you want to use the same technique there:
cout << static_cast<void*>(p+1) << endl;
However, the difference between two pointers is a signed whole number (the precise type, if you ever need it, is defined as ptrdiff_t in <cstddef>, but fortunately you don’t need to worry about that with cout), so you just want to use that directly:
cout << (p+1) - p << endl;
cout << reinterpret_cast<char*>(p+1) - reinterpret_cast<char*>(p) << endl;
cout << (q - p) << endl;
That second line casts to char* because the size of a char is always 1. That’s a big hint what’s going on.
As for what’s going on under the hood: compare the numbers you get to sizeof(*p) and sizeof(*q), which are the sizes of the objects p and q point to.
The pointer values that are printed are likely to change on every execution (see why the addresses of local variables can be different every time and Address Space Layout Randomization)
I get an answer of 00EFF680 for everytime I compare the adresss p with another pointer.
int val = 20;
double valD = 20;
int *p = &val;
cout << p == p + 1;
It is translated into (cout << p) == p + 1; due to the higher precedence of operator << on operator ==.
It print the hexadecimal value of &val, first address on the stack frame of the main function.
Note that in the stack, address are decreasing (see why does the stack address grow towards decreasing memory addresses).
I get an answer of 00EFF670 for everytime I compare the address of q with another pointer.
double *q = &valD;
cout << q == q + 1;
It is translated into (cout << q) == q + 1; due to the precedence of operator << on operator ==.
It prints the hexadecimal value of &valD, second address on the stack frame of the main function.
Note that &valD <= &val - sizeof(decltype(valD) = double) == &val - 8 since val is just after valD on the stack. It is a compiler choice that respects some alignment constraints.
I get an answer of 15726208 when I look at the pointer value of p.
cout << (unsigned long)(p) << endl;
It just prints the decimal value of &val
And I get an answer of 15726212 When I look at the pointer value of p + 1.
int *p = &val;
cout << (unsigned long) (p + 1) << endl;
It prints the decimal value of &val + sizeof(*decltype(p)) = &val + sizeof(int) = &val + 4 since on your machine int = 32 bits
Note that if p is a pointer to type t, p+1 is p + sizeof(t) to avoid memory overlapping in array indexing.
Note that if p is a pointer to void, p+1 should be undefined (see void pointer arithmetic)
I get an answer of 15726192 when I look at the pointer value of q
cout << (unsigned long)(q) << endl;
It prints the decimal value of &valD
And I get an answer of 15726200 Wehn I look at the pointer value of q + 1.
cout << (unsigned long) (q + 1) << endl;
It prints the decimal value of &val + sizeof(*decltype(p)) = &valD + sizeof(double) = &valD + 8

How is an array aligned in C++ compared to a type contained? 2

Following the topic How is an array aligned in C++ compared to a type contained? I made an experiment.
Here is the code:
#include<iostream>
using namespace std;
int main()
{
const int N = 12;
{
float p1[N], p2[N];
cout << p1 << " " << p2 << " " << p2 - p1 << endl;
}
{
float* p1, *p2;
// allocate memory
p1 = new float[N];
p2 = new float[N];
cout << p1 << " " << p2 << " " << p2 - p1 << endl;
delete[] p1;
delete[] p2;
}
}
According to the cited question and wiki I would expect that p1 and p2 would be sizeof(float) == 4 bytes aligned. But the result is:
0x7fff4fd2b410 0x7fff4fd2b440 12
0x7f8cc9c03bd0 0x7f8cc9c03c00 12
Same 12 distance between arrays for N = 9, 11 and 12. Distance (p2-p1) is 8 for N = 8.
So it looks like float arrays is 16 bytes aligned. Why?
P.S.
My processor is Intel Core i7
Compiler - g++ 4.6.3
It appears that putting arrays in a structure one can get 10 floats distance:
const int N = 10;
struct PP{
float p1[N], p2[N];
};
int main() {
PP pp;
cout << pp.p1 << " " << pp.p2 << " " << pp.p2 - pp.p1 << endl;
}
0x7fff50139440 0x7fff50139468 10
Memory allocated by operator new always has suitable alignment for any object type, whatever the actual type being created. Additionally, it may also have a wider alignment (for example, alignment with a cache line) to improve performance.
If you replace your dynamic arrays with automatic ones (or better still, make them consecutive members of a class), then you may see narrower alignments. Or you may not; the exact details of how objects are aligned are up to the compiler, as long as it meets the minimum requirement for the type.