Использование оператора равенства == для сравнения двух строк на равенство в C - PullRequest
12 голосов
/ 14 октября 2010
int main (int argc, **argv)
{
       if (argv[1] == "-hello")
            printf("True\n");
       else
            printf("False\n");
}
# ./myProg -hello
False

Почему?Я понимаю, strcmp(argv[1], "-hello") == 0 возвращает true ... но почему я не могу использовать оператор равенства для сравнения двух строк C?

Ответы [ 9 ]

17 голосов
/ 14 октября 2010

Потому что argv[1] (например) фактически является указателем на строку. Поэтому все, что вы делаете, это сравниваете указатели.

12 голосов
/ 14 октября 2010

Вы не можете сравнивать строки в C с ==, потому что компилятор C на самом деле не имеет понятия о строках за пределами строкового литерала.

Компилятор видит сравнение с char* с обеих сторон, поэтому он выполняет сравнение указателей (которое сравнивает адреса, хранящиеся в указателях)

11 голосов
/ 14 октября 2010

В C, потому что в большинстве случаев массив «превращается в указатель на свой первый элемент».

Итак, когда у вас есть массив "foobar" и вы используете его в большинстве контекстов, он превращается в указатель:

if (name == "foobar") /* ... */; /* comparing name with a pointer */

Что вы хотите сравнить содержимое массива с что-то . Вы можете сделать это вручную

if ('p' == *("foobar")) /* ... */; /* false: 'p' != 'f' */
if ('m' == *("foobar"+1)) /* ... */; /* false: 'm' != 'o' */
if ('g' == *("foobar"+2)) /* ... */; /* false: 'g' != 'o' */

или автоматически

if (strcmp(name, "foobar")) /* name is not "foobar" */;
7 голосов
/ 14 октября 2010

Потому что нет такой вещи как строка C.

В C строка обычно представляет собой массив char или указатель на char (что почти совпадает). Сравнение указателя / массива с константным массивом не даст ожидаемых результатов.

ОБНОВЛЕНИЕ: то, что я имел в виду под «без строки C», в C. строки нет. То, что обычно называют «C строкой», не зависит от языка (как «строка Pascal»), это представление строк в виде линейного массива символов с нулевым символом в конце.

5 голосов
/ 14 октября 2010

В C строковые значения (включая строковые литералы) представлены в виде массивов char, за которым следует терминатор 0, и вы не можете использовать оператор == для сравнения содержимого массива;язык просто не определяет операцию.

За исключением случаев, когда это операнд оператора sizeof или & или когда это строковый литерал, используемый для инициализации другого массива в объявлении, выражение с типом "массив N-элементов"из T "будет иметь свой тип неявно преобразуется (распад) в тип" указатель на T ", а значением выражения будет адрес первого элемента массива.

Поэтому, когда вы пишете

if (argv[1] == "-hello")

, компилятор неявно преобразует выражение "-hello" из типа "массив из 7 элементов char" в "указатель на char" (argv[1] ужетип указателя), а значением выражения является адрес символа '-'.Так что == сравнивает два значения указатель , которые (скорее всего) никогда не будут равны, поскольку "-hello" и argv[1] (скорее всего) занимают разные области в памяти.

Вот почему вы должны использовать библиотечные функции, такие как strcmp(), для сравнения строковых значений.

3 голосов
/ 14 октября 2010

Поскольку строки C не существуют как таковые. Это массивы символов, оканчивающиеся на \0.

Оператор равенства == проверит, что указатель на первый элемент массива совпадает. Это не будет сравнивать лексикографически.

С другой стороны, "-hello" == "-hello" может вернуть ненулевое значение, но это не означает, что оператор == сравнивает лексикографически Это связано с другими фактами.

Если вы хотите сравнить лексикографически, вы всегда можете

#define STR_EQ(s1,s2)    \
   strcmp(s1,s2) == 0

Чтение сложнее. Я вижу, что вы помечены как c ++. Так что вы могли бы

 std::string arg1 ( argv[1] );

 if (arg1 == "-hello"){
    // yeahh!!!
 }
 else{
    //awwwww
 }
2 голосов
/ 14 октября 2010

Строки не являются родными типами в C. В этом примере вы сравниваете два указателя.Один к вашему первому аргументу, а другой - статический массив символов с содержимым «-hello».

Вы действительно хотите использовать strncmp или что-то подобное.

1 голос
/ 14 октября 2010

Когда вы используете ==, вы сравниваете указатели. То есть он вернет true, если два операнда ссылаются на одну и ту же строку в памяти. Поэтому он не подходит для лексикографического сравнения строк.

0 голосов
/ 14 октября 2010

Потому что строки C - это массив символов.Массивы - это просто указатели на первый элемент в массиве, и когда вы сравниваете два указателя с помощью ==, он сравнивает адрес памяти, на который они указывают, а не значения, на которые они указывают.

...