Ответ 1
Потому что argv[1]
(например) на самом деле является указателем на строку. Итак, все, что вы делаете, это сравнение указателей.
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?
Потому что 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 (что почти то же самое). Сравнение указателя/массива с массивом const не даст ожидаемых результатов.
UPDATE: что я имел в виду под "no C string", нет строки в C. То, что обычно называют "строкой C", не зависит от языка (поскольку "строка Pascal" есть), это представление строк как линейный массив символов с нулевым символом.
В C строковые значения (включая строковые литералы) представлены в виде массивов char
, за которыми следует 0-терминатор, и вы не можете использовать оператор ==
для сравнения содержимого массива; язык просто не определяет операцию.
За исключением случаев, когда он является операндом операторов sizeof
или &
или когда это строковый литерал используется для инициализации другого массива в объявлении, выражение с типом "N-элементный массив из T" будет иметь тип, неявно преобразованный (распад), чтобы ввести "указатель на T", а значение выражения будет адресом первого элемента массива.
Итак, когда вы пишете
if (argv[1] == "-hello")
компилятор неявно преобразует выражение "-hello"
из массива "7-элементный элемент char" в "указатель на char" (argv[1]
уже является типом указателя), а значение выражения адрес символа '-'
. Итак, то, что сравнивает ==
, - это два значения указателя, которые (скорее всего) никогда не будут равны, поскольку "-hello"
и argv[1]
(скорее всего) занимают разные регионы в памяти.
Вот почему вы должны использовать библиотечные функции, такие как strcmp()
для сравнения строковых значений.
Потому что строки C не существуют как таковые. Это char массивы, заканчивающиеся на \0
.
Оператор равенства ==
будет проверять, что указатель на первый элемент массива один и тот же. Он не будет сравнивать лексикографически.
С другой стороны, "-hello" == "-hello"
может возвращать ненулевое значение, но это не означает, что оператор ==
сравнивает лексикографию. Это связано с другими фактами.
Если вы хотите сравнить lexicographycally, вы всегда можете
#define STR_EQ(s1,s2) \
strcmp(s1,s2) == 0
Чтение сложнее. Я вижу, что вы отметили как С++. Таким образом, вы могли
std::string arg1 ( argv[1] );
if (arg1 == "-hello"){
// yeahh!!!
}
else{
//awwwww
}
Строки не являются родными типами в C. То, что вы сравниваете в этом примере, - это два указателя. Один для вашего первого аргумента, а другой - это статический массив символов с содержимым "-hello".
Вы действительно хотите использовать strncmp или что-то подобное.
Когда вы используете ==, вы сравниваете указатели. То есть, он вернет true, если два операнда относятся к одной и той же строке в памяти. Поэтому он непригоден для использования при сравнении строк лексикографически.
Поскольку строки C представляют собой массив символов. Массивы просто указывают на первый элемент в массиве, и когда вы сравниваете два указателя, используя ==, он сравнивает адрес памяти, на который они указывают, а не те значения, которые они указывают.