55

Can someone please explain to me why the output from the following code is saying that arrays are not equal?

int main()
{

    int iar1[] = {1,2,3,4,5};
    int iar2[] = {1,2,3,4,5};

    if (iar1 == iar2)
        cout << "Arrays are equal.";
    else
        cout << "Arrays are not equal.";

    return 0;   
}
emlai
  • 37,861
  • 9
  • 87
  • 140
vladinkoc
  • 763
  • 1
  • 6
  • 13
  • 30
    Use `std::array` or `std::vector`. C arrays have no single advantage and they only bring pain and sorrow. No excuses. – daknøk Oct 12 '12 at 20:14
  • 4
    @daknøk What about interop with C? – weberc2 Mar 02 '15 at 01:12
  • 3
    @weberc2 `.data()`. No excuses. – emlai Apr 19 '16 at 23:13
  • 6
    No it doesn't but it's there for C interop. And no, converting C arrays to std::arrays, just to check for equality, is completely unacceptable. It involves copying. When `std::array_view` is in the standard we'll have a sensible way of comparing raw arrays resulting from C interop. – emlai Apr 20 '16 at 00:47
  • Your declared variables are pointers to the first int elements in two seperate arrays in two distinct locations in memory. They are not equal (the addresses are different) and so the conditional test evaluates to false. – Reno Feb 20 '20 at 10:11

11 Answers11

88
if (iar1 == iar2)

Here iar1 and iar2 are decaying to pointers to the first elements of the respective arrays. Since they are two distinct arrays, the pointer values are, of course, different and your comparison tests not equal.

To do an element-wise comparison, you must either write a loop; or use std::array instead

std::array<int, 5> iar1 {1,2,3,4,5};
std::array<int, 5> iar2 {1,2,3,4,5};

if( iar1 == iar2 ) {
  // arrays contents are the same

} else {
  // not the same

}
Praetorian
  • 100,267
  • 15
  • 224
  • 307
  • 3
    +1 for the only answer with the word "decay" (or anything else explicitly saying so). – chris Oct 12 '12 at 20:19
  • 5
    "... you must either write a loop...." Better would be to use std::equal. Not to detract from your point that using raw arrays is the main problem. – Ben Oct 19 '12 at 17:40
  • For people like me who got something like "implicit instantiation of undefined template ..." when trying to use std::array, try #import or #include . – Golden Thumb Mar 01 '18 at 03:36
  • 2
    Good explanation of "decay": https://stackoverflow.com/a/1461449/108238 – schoetbi Sep 30 '19 at 05:51
66

Since nobody mentioned it yet, you can compare arrays with the std::equal algorithm:

int iar1[] = {1,2,3,4,5};
int iar2[] = {1,2,3,4,5};

if (std::equal(std::begin(iar1), std::end(iar1), std::begin(iar2)))
    cout << "Arrays are equal.";
else
    cout << "Arrays are not equal.";

You need to include <algorithm> and <iterator>. If you don't use C++11 yet, you can write:

if (std::equal(iar1, iar1 + sizeof iar1 / sizeof *iar1, iar2))
15

You're not comparing the contents of the arrays, you're comparing the addresses of the arrays. Since they're two separate arrays, they have different addresses.

Avoid this problem by using higher-level containers, such as std::vector, std::deque, or std::array.

Fred Larson
  • 56,061
  • 15
  • 106
  • 157
  • 5
    It's important to note that these containers have implemented their own `==` operator that performs this check. – tadman Oct 12 '12 at 20:23
6

Array is not a primitive type, and the arrays belong to different addresses in the C++ memory.

Paul S.
  • 4,066
  • 9
  • 32
  • 51
5

Nobody mentions memcmp? This is also a good choice.

/* memcmp example */
#include <stdio.h>
#include <string.h>

int main ()
{
  char buffer1[] = "DWgaOtP12df0";
  char buffer2[] = "DWGAOTP12DF0";

  int n;

  n=memcmp ( buffer1, buffer2, sizeof(buffer1) );

  if (n>0) printf ("'%s' is greater than '%s'.\n",buffer1,buffer2);
  else if (n<0) printf ("'%s' is less than '%s'.\n",buffer1,buffer2);
  else printf ("'%s' is the same as '%s'.\n",buffer1,buffer2);

  return 0;
}

Ref: http://www.cplusplus.com/reference/cstring/memcmp/

Xiangyi Meng
  • 85
  • 2
  • 5
3

If you are reluctant to change your existing code to std::array, then use a couple of methods instead which takes non-type template arguments :

//Passed arrays store different data types
template <typename T, typename U, int size1, int size2>
bool equal(T (&arr1)[size1], U (&arr2)[size2] ){
    return false;
}

//Passed arrays store SAME data types
template <typename T, int size1, int size2>
bool equal(T (&arr1)[size1], T (&arr2)[size2] ){
    if(size1 == size2) {
        for(int i = 0 ; i < size1; ++i){
            if(arr1[i] != arr2[i]) return false;
        }
        return true;
    }
    return false;
}

Here is the demo. Note that, while calling, we just need to pass the array variables e.g. equal(iar1, iar2) in your case, no need to pass the size of arrays.

Saurav Sahu
  • 9,755
  • 5
  • 42
  • 64
1

You are comparing the addresses instead of the values.

Rahul Tripathi
  • 152,732
  • 28
  • 233
  • 299
1

Both store memory addresses to the first elements of two different arrays. These addresses can't be equal hence the output.

  • almost correct @Vachaspati -- they could be equal (for example, after the command `iar1 = iar2;`) but in this case, straight after initialisation, they won't be. – alle_meije May 02 '20 at 05:27
0

Right. In most, if not all implementations of C, the array identifier can be implicitly casted to a pointer to the first element (i.e. the first element's address). What you're doing here is comparing those addresses, which is obviously wrong.

Instead, you need to iterate over both arrays, checking each element against each other. If you get to the end of both without a failure, they're equal.

slugonamission
  • 9,328
  • 29
  • 39
  • 1
    In *none* is the array identifier actually the address of the first element. The array identifier is actually the array. In `int arr[6]`, `arr` refers to a value of type `int[6]`. That value is implicitly convertible to `int*`, with the value `&arr[0]` (often called decaying). But an array is not "actually" a pointer. – GManNickG Oct 12 '12 at 20:25
0

When we use an array, we are really using a pointer to the first element in the array. Hence, this condition if( iar1 == iar2 ) actually compares two addresses. Those pointers do not address the same object.

vladinkoc
  • 763
  • 1
  • 6
  • 13
0

If you are willing to use std::array instead of built-in arrays, you may use:

std::array<int, 5> iar1 = {1,2,3,4,5};
std::array<int, 5> iar2 = {1,2,3,4,5};

if (iar1 == iar2)
R Sahu
  • 196,807
  • 13
  • 136
  • 247