What does subtracting two arrays do in c++? - c++

For example if I subtracted an array with size 3 from an array with size 2, it returns 3 no matter what is inside. Why is that?
Ex:
int a[2] = {1,2};
int b[3] = {999,999,999};
cout << a-b;
And the output is 3

The first question here that, what is the subtraction of two arrays?
If you are mentioning the subtraction of the elements that have the same indexes, you have to make sure that the array's size is equal.
Then iterate through both arrays and subtract one to another using loop.
The thing you want to achieve results in undefined behavior.
You can alternatively use the overloaded '-' operator to subtract two array objects but it is a little bit complicated.

This simply happens, because your example does substract pointers of int, instead of the vector.
What happens is this:
&a[0] - &b[0]
I assume you try to achieve a vector substraction instead. One approach is to overload the operatror -.
Have a look here, how operator overloading can be done: What are the basic rules and idioms for operator overloading?

it returns 3 no matter what is inside
No, it does not always return 3.
It depends on the compiler/linker/library/platform/many other factors.
For example, on my machine the g++ compiler and the MSVC get two different results.
You should never make any assumptions and rely on this behavior.
#include <iostream>
using namespace std;
int main(int argc, char **argv) {
{
int a[2] = {1, 2};
int b[3] = {999, 999, 999};
cout << a - b << endl;
cout << static_cast<void *>(a) << ' ' << static_cast<void *>(b) << endl;
}
{
int a[2] = {1, 2};
int middle_array[2] = {1, 2};
int b[3] = {999, 999, 999};
cout << a - b << endl;
cout << static_cast<void *>(a) << ' ' << static_cast<void *>(b) << endl;
}
return 0;
}
With G++
$g++ t3.cpp && ./a.exe
3
0xffffcc28 0xffffcc1c
5
0xffffcc14 0xffffcc00
With MSVC
cl t3.cpp && t3.exe
-6
00000012814FFB00 00000012814FFB18
-8
00000012814FFB08 00000012814FFB28
P.S. For the curious.
These are test results of two different machines(g++):
4
0x7ffcdaa00640 0x7ffcdaa00630
8
0x7ffcdaa00620 0x7ffcdaa00600
-2
0x7ffd969a2904 0x7ffd969a290c
-4
0x7ffd969a28fc 0x7ffd969a290c

Related

Negative Subscript of an array in c++

Lets say we have an int array "arr" of size 5 then &arr points to whole array of 5 int.
But when I do like &arr[-1] I don't get any error, Can somebody explain what does this means.
int arr[5] = {1, 2, 3, 4, 5};
std::cout << &arr << std::endl; // 0x61fea0
std::cout << &arr[-1] << std::endl; // 0x61fe9c (0x4 less than previous)
This is because of the relationship that arrays and pointers share. A negative index might still point at an address within the bounds and won't result in an error

cpp double pointer vs 2 dimensional array pointer

#include <iostream>
int main() {
int a[2][2] = {{1,2}, {3,4}};
int *c = *a;
int **b = &c;
std::cout << **(a+1); // outputs 3
std::cout << **(b+1); // segmentation fault
}
Why does one cout results in segmentation fault and other doesn't? Shouldn't they be referring to the same value?
Lets start with
int *c;
Actually what comes before is not that relevant, because c is just a pointer and then here
int **b = &c;
you store the address of c in b. The address of c has nothing to do with what value is stored in c. c is just a pointer, taking its adress doesn't let you magically access a 2d array.
cout << **(b+1); // segmentation fault
Already b+1 is undefined behaviour. Dereferencing that pointer cannot give you something meaningful.
PS: tbh I cannot tell you how to use the double pointers correctly here. Once I started to learn c++ I unlearned anything I knew about working with arrays via pointers. Use std::vector or std::array and save yourself some headaces.
In this statement
cout << **(b+1);
the expression b+1 points outside the array (that is more precisely outside the object c). You should write
cout << *( *b + 2 );
The dereferenced pointer b points to the pointer to the first element of the two-dimensional array. When adding to it the number of elements in the array of the type int[2] you will get the pointer to the first element of the second "row" of the two-dimensional array. Now you need again to dereference it to output the pointed value.
I rewrote the code to highlight what is happening, as below:
#include <iostream>
int main() {
int a[2][2] = {{1,2}, {3,4}};
int *c[2] = {a[0], a[1]};
int **b = c;
std::cout << **(a ) << ','; // outputs 1
std::cout << **(b ) << ";\n"; // outputs 1
std::cout << **(a+1) << ','; // outputs 3
std::cout << **(b+1) << ";\n"; // outputs 3
}
LINK: https://ideone.com/ixj3NV
UPDATED LINK: https://ideone.com/g7jjVN
(Clarified the original source to extend the program)

Pointers difference

Say I declared an arrayint a[]={1,2,3,4,5};, when I do (*(&a+1)-a), it prints 5.
I came to know that *(&a+1) takes me to the end of an array, and as sizeof(a)=20.
So does pointer arithmetic takes me ahead of size of allocated container?
Also I am little bit confused on pointer arithmetic, why it prints 5 rather than 20?
The result of pointer arithmetic is is in units of the dereferenced type.
If you have a pointer to an int then the units will be in int elements.
If you have a pointer to an int[5] then the units will be in int[5] elements, which are exactly 5 times as big.
For your program above, a and &a will have the same numerical value,and I believe that's where your whole confusion lies.You may wonder that if they are the same,the following should give the next address after a in both cases,going by pointer arithmetic:
(&a+1) and (a+1)
But it's not so!!Base address of an array (a here) and Address of an array are not same! a and &a might be same numerically ,but they are not the same type. a is of type * while &a is of type (*)[5],ie , &a is a pointer to (address of ) and array of size 5.But a as you know is the address of the first element of the array.Numerically they are the same as you can see from the illustration using ^ below.
1 2 3 4 5
^ // ^ stands at &a
1 2 3 4 5
^ // ^ stands at (&a+1)
1 2 3 4 5
^ //^ stands at a
1 2 3 4 5
^ // ^ stands at (a+1)
Hope this will clear the doubts.
Pointer arithmetic is not same as arithmetic operation (addition/subtraction) between hexadecimal values. Following example demonstrates both.
int main()
{
int a[] = { 1, 2, 3, 4, 5 };
int * pintx = *(&a + 1);
int * pinty = a;
cout << "pintx = " << pintx << endl;
cout << "pinty = " << pinty << endl;
cout << "Pointer Arithmetic : Ans = " << (*(&a + 1) - a) << endl;
// Prints 5
cout << "Pointer Arithmetic : Ans = " << (pintx - pinty) << endl;
// Save as above, Print 5
cout << "Hexadecimal Subtraction: Ans = " << ((int)pintx - (int)pinty) << endl;
// Prints 20, as you expect
return 0;
}
Hope this helps.
So does pointer arithmetic takes me ahead of size of allocated container?
No. Not the "size of allocated container", but the size of the dereferenced type. sizeof(a) is 20 because as an object the type of a is int[5] instead of int*, and the type of &a is int[5]*. It will be clearer if I rewrite your example as below:
typedef int Int5[5];
Int5 a = { 1, 2, 3, 4, 5 };
Also I am little bit confused on pointer arithmetic, why it prints 5 rather than 20?
(*(&a+1)-a) is 5 because in this case a is interpreted as int*.

C++ begin/end(arr) on a pointer - no matching function for call to ‘begin(int**&)’ [duplicate]

This question already has answers here:
error: no matching function for call to 'begin(int*&)' c++
(3 answers)
Closed 6 years ago.
I'd like to get length of an array. I have this code:
#include <iterator>
#include <iostream>
#include <string>
using namespace std;
void printArrLen(int arr[]);
int testArr [3] = {1, 4, 5};
int main() {
printArrLen(testArr);
cout << "main/testArr; Memory address: " << testArr << ", value: " << *testArr << endl;
cout << end(testArr) << endl;
}
void printArrLen(int arr[]) {
cout << "printArrLen/arr; Memory address: " << arr << ", value: " << *arr << endl;
cout << "printArrLen/testArr; Memory address: " << testArr << ", value: " << *testArr << endl;
// This works:
cout << end(testArr) << endl;
// This doesn't work - no matching function for call to 'end(int*&)':
// cout << end(arr) << endl;
// Doesn't work:
// cout << "arrLen: " << end(arr) - begin(arr) << endl;
}
Output:
printArrLen/arr; Memory address: 0x601318, value: 1
printArrLen/testArr; Memory address: 0x601318, value: 1
0x601324
main/testArr; Memory address: 0x601318, value: 1
0x601324
Uncommenting cout << end(arr) << endl; in printArrLen gives no matching function for call to 'end(int*&)'
I'm aware that begin/end(arr) wont work if arr is a pointer.
Why do they work on testArr in printArrLen and main, if the testArr seems to be a pointer too? How it can be proven in printArrLen that testArr is not a pointer and arr is while they both seem to contain a memory address?
I'm aware that begin/end(arr) wont work if arr is a pointer. Why do they work on testArr in printArrLen and main, if the testArr seems to be a pointer too?
Pointers are not arrays.
In your code,
testArr is array which has been initialised with 3 elements.
arr is array parameter. Array parameter is special in the sense that the array decays to pointer, so what is actually passed to the function printArrLen is a pointer (to arr first element).
Btw, you don't have to provide array size when you initialise it. This would do as well (and better):
int testArr[] = {1, 4, 5};
I'd like to get length of an array.
[...]
void printArrLen(int arr[]);
Not like this. arr in this function is actually a pointer to the first element of the array. Or more precisely, it may point to the first element of an array. It's just an int* and could point anywhere. In any case, there is no size information anymore inside of the function. You simply cannot get it.
The [] syntax is just there to confuse you. But don't take my word on it -- ask your compiler by trying this piece of code:
void printArrLen(int arr[]) {}
void printArrLen(int* arr) {}
You will see that it will complain about a redefinition.
int testArr [3] = {1, 4, 5};
testArr, in contrast to the arr parameter above, is an array, and carries the size information in its type.
int main() {
printArrLen(testArr);
Here you pass to the function a pointer to the first element of testArr, i.e. an int* pointing to the "1" element.
// This works:
cout << end(testArr) << endl;
Because testArr is an array.
// This doesn't work - no matching function for call to 'end(int*&)':
// cout << end(arr) << endl;
Because arr is a pointer.
Use std::vector if the array's size is only known at runtime, or std::array if it's already known at compile time. Both containers always know their own size.
How it can be proven in printArrLen that testArr is not a pointer
and arr is while they both seem to contain a memory address?
This question makes less sense than it seems.
Consider this:
int main()
{
int i = 0;
double d = 0.0;
}
Now, how can you "prove" that i is not a double but d is?
The answer is that you do not have to "prove" it, because, obviously, you already know.
Technically, there is another answer to your question, of course, and that is using typeid...
#include <typeinfo>
#include <typeindex>
#include <iostream>
void printArrLen(int arr[]);
int testArr [3] = {1, 4, 5};
int anotherTestArr [3] = {1, 4, 5};
int yetAnotherTestArr [4] = {1, 4, 5, 6};
int main() {
printArrLen(testArr);
}
void printArrLen(int arr[]) {
std::cout << (std::type_index(typeid(arr)) == std::type_index(typeid(testArr))) << "\n";
std::cout << (std::type_index(typeid(anotherTestArr)) == std::type_index(typeid(testArr))) << "\n";
std::cout << (std::type_index(typeid(yetAnotherTestArr)) == std::type_index(typeid(testArr))) << "\n";
}
This does not have any direct use for you, but it is of great educational value. It will print:
0
1
0
This example demonstrates that arrays of different sizes are different types, and pointers are different types from all array types.
testArr is not a pointer, it is an array with 3 elements.
arr is a pointer - there is not enough knowledge to make begin and end work, because the compiler does not know that it's pointing to an array (and what the size of the hypothetical array is).
My suggestion is: use either std::array or std::vector, depending on what you need to do. If you want to use old-school arrays, change printArrLen to take an array reference:
template <size_t N>
void printArrLen(int (&arr)[N]) {
/* ... */
}
wandbox example

Why does dereferencing an array or not result in the same address?

In C++, I wrote the following simple main:
int main() {
char test[100];
void* a = (void*) test;
void* b = (void*) &test;
std::cout << a << " " << b << std::endl;
return 0;
}
And it gives me the same result for a and b. Why is this? I would expect from the notation that the second be the address of the first..
In C++, arrays are converted to pointer to first element of the array. test is pointer to first element test[0]. &test is the address of entire array test. Although, the type of test and &test are different, their values are same and that's why you are getting the same value.
For example
int a[3] = {5, 4, 6};
Look at the diagram below:
For detailed explanation read this answer.