сравнить два равных массива в c, но вывод показывает неравный - PullRequest
4 голосов
/ 12 января 2012

После долгого перерыва я вернулся к Си, но запутался даже в некоторых простых вопросах. Итак, один здесь.

Вот простой код:

 #include<stdio.h>

 int main() {

    char str1[]="hello";
    char str2[]="hello";

    if(str1==str2)
            printf("equal");  
    else
            printf("unequal");
} 

Выход: неравные

но когда я попробовал это, это сработало

  char *str1="hello";
  char *str2="hello";

выход равна

Пожалуйста, если кто-нибудь может предоставить подробное объяснение этого. Может кто-нибудь сказать мне, что именно С99 стандарт говорит о ситуации ???

Ответы [ 7 ]

12 голосов
/ 12 января 2012

Когда вы делаете == с указателями (это то, что str1 и str2 в обоих случаях 1 ), все, что вы делаете, сравнивает два адреса, чтобы увидеть, совпадают ли они,Когда вы делаете

char str1[]="hello";
char str2[]="hello";

Вы создаете в стеке два массива, которые содержат "hello".Они, безусловно, находятся в разных местах памяти, поэтому str1 == str2 равно false.Это похоже на

char str1[6];
str1[0] = 'h';
str1[1] = 'e';
str1[2] = 'l';
str1[3] = 'l';
str1[4] = 'o';
str1[5] = '\0'; 

// and the same thing for str2

Когда вы делаете

char *str1="hello";
char *str2="hello";

Вы создаете два указателя на глобальные данные "hello".Компилятор, видя, что эти строковые литералы одинаковы и не могут быть изменены, заставит указатели указывать на один и тот же адрес в памяти, а str1 == str2 равен true.

Для сравнения содержимого из двух char* s, используйте strcmp:

// strcmp returns 0 if the two strings are equal
if (strcmp(str1, str2) == 0)
    printf("Equal");
else
    printf("Not equal");

Это примерно эквивалентно

char *a, *b;

// go through both strings, stopping when we reach a NULL in either string or
// if the corresponding characters in the strings don't match up
for (a = str1, b = str2; *a != '\0' && *b != '\0'; ++a, ++b)
    if (*a != *b)
        break;

// print Equal if both *a and *b are the NULL terminator in
// both strings (i.e. we advanced a and b to the end of both
// strings with the loop)
if (*a == '\0' && *b == '\0')
     printf("Equal");
else
     printf("Not equal");

1 В версии char* это действительно так.В версии char[] str1 и str2 действительно массивы , а не указатели, однако при использовании в str1 == str2 они распадаются на указатели на первые элементы массивов, поэтому ониэквивалент указателей в этом сценарии.

2 голосов
/ 12 января 2012

Вы сравниваете указатели со строками, а не с самими строками, но, поскольку они представляют собой две разные строки, они не равны "==".

Если вы сравниваете строки в C, вам нужно использовать strcmp (str1, str2) a'la

if(strcmp(str1, str2) == 0) {

Слово предостережения; если бы вы объявили строки как char * вместо char [], некоторые компиляторы фактически отобразили бы ваше сравнение как равное, так как компилятор понимает, что две строки равны, и объединяет их в одну. Это означает, что они оба будут указывать на одну и ту же строку, и сравнение указателей будет истинным.

Был укушен этим разом, никогда, черт возьми, компилятором VAX ...:)

0 голосов
/ 12 января 2012

Кстати, второй тоже может быть unequal. При использовании equal на большинстве платформ возможна оптимизация компилятора, поскольку эти две строки hello не обязательно должны храниться в одном и том же статическом пространстве памяти.

0 голосов
/ 12 января 2012

В первом случае вы сравниваете указатели со строками, которые, конечно, находятся в двух разных позициях и не будут равны.Во втором случае вы сравниваете два символа, указанные в начале строки, которые оба равны 'h' и, конечно же, равны.

0 голосов
/ 12 января 2012

Проблема в том, что при использовании

* str1 = "привет";* str2 = "hello";

Компилятор может оптимизировать это для использования одного пространства памяти, и поэтому str1 и str2 оба будут указывать на одно и то же пространство памяти.Однако при использовании записи массива компилятор, скорее всего, создает два массива в памяти, и поэтому указатели указывают на разные области памяти.

при использовании == он проверяет равенство указателей, а неструны.

0 голосов
/ 12 января 2012

Вы не сравниваете массивы, вы сравниваете указатели с данными. В первом случае, когда вы объявляете char [], вы получаете два разных массива по двум адресам, поэтому они не равны. Во втором случае вы получаете постоянный массив, поэтому оба указателя могут получить одинаковый адрес, так как массив const не может быть изменен.

0 голосов
/ 12 января 2012

Строки (char указатели) в C должны сравниваться с strcmp() или одной из его родственных функций.

Также не должно работать правильно (т. Е. Вы всегда должны использоватьstrcmp() при сравнении строк), но причина, по которой последний, вероятно, сработал, заключалась в том, что во втором примере у вас есть одна строка в памяти (вероятно), которая "привет", и оба str1 и str2в конечном итоге указываем на это, как на оптимизацию.

Первый, однако, фактически требует создания двух отдельных символьных массивов, поэтому они не совпадают с указателем.

...