Использование оператора равенства == для сравнения двух строк на равенство в C
int main (int argc, **argv)
{
if (argv[1] == "-hello")
printf("True\n");
else
printf("False\n");
}
# ./myProg -hello Ложь
Зачем? я понимаю strcmp(argv[1], "-hello") == 0
возвращает true... но почему я не могу использовать оператор равенства для сравнения двух строк C?
9 ответов
Так как argv[1]
(например) фактически является указателем на строку. Поэтому все, что вы делаете, это сравниваете указатели.
Вы не можете сравнивать строки в C с ==, потому что компилятор C на самом деле не имеет понятия о строках за пределами строкового литерала.
Компилятор видит сравнение с char*
с любой стороны, поэтому выполняется сравнение указателей (которое сравнивает адреса, хранящиеся в указателях)
В 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" */;
Потому что нет такой вещи как строка C.
В C строка обычно представляет собой массив char или указатель на char (что почти одинаково). Сравнение указателя / массива с константным массивом не даст ожидаемых результатов.
ОБНОВЛЕНИЕ: то, что я имел в виду под "без строки C", в C. нет строки. То, что обычно называют "строкой C", не зависит от языка (как "строка Паскаля"), это представление строк в виде нуля линейный массив символов
В C строковые значения (включая строковые литералы) представлены как массивы char
за ним следует терминатор 0, и вы не можете использовать ==
оператор для сравнения содержимого массива; язык просто не определяет операцию.
За исключением случаев, когда это операнд sizeof
или же &
операторы, или когда это строковый литерал, используемый для инициализации другого массива в объявлении, выражение с типом "массив из N элементов из T" будет неявно преобразовано в свой тип (затухание) в тип "указатель на T", и Значением выражения будет адрес первого элемента массива.
Поэтому, когда вы пишете
if (argv[1] == "-hello")
компилятор неявно преобразует выражение "-hello"
от типа "7-элементный массив символов" до "указатель на символ" (argv[1]
это уже тип указателя), а значением выражения является адрес символа '-'
, И что ==
Сравнение двух значений указателей, которые (скорее всего) никогда не будут равны "-hello"
а также argv[1]
(скорее всего) занимают разные области памяти.
Вот почему вы должны использовать библиотечные функции, такие как strcmp()
сравнить строковые значения.
Потому что строки 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
}
Строки не являются родными типами в C. В этом примере вы сравниваете два указателя. Один к вашему первому аргументу, а другой - статический массив символов с содержимым "-hello".
Вы действительно хотите использовать strncmp или что-то подобное.
Когда вы используете ==, вы сравниваете указатели. То есть он вернет true, если два операнда ссылаются на одну и ту же строку в памяти. Следовательно, он не подходит для лексикографического сравнения строк.
Потому что строки C - это массив символов. Массивы - это просто указатели на первый элемент в массиве, и когда вы сравниваете два указателя с помощью ==, он сравнивает адрес памяти, на который они указывают, а не значения, на которые они указывают.