Правильно ли я, что strcmp эквивалентен (и безопасен) для литералов? - PullRequest
15 голосов
/ 16 января 2009

Мы все знаем, что проблема может быть вызвана переполнением, и именно поэтому strn * существуют - и большую часть времени они имеют смысл. Однако я видел код, который использует strncmp для сравнения параметров командной строки, например так:

if(... strncmp(argv[i], "--help", 6) == 0

Теперь я бы подумал, что это не нужно и, возможно, даже опасно (для более длинных параметров было бы легко неправильно подсчитать символы в литерале).

strncmp останавливается на пустых значениях, и код уже предполагает, что argv [i] завершается нулем. Любой строковый литерал гарантированно заканчивается нулем, так почему бы не использовать strcmp?

Возможно, я что-то упускаю, но я видел это несколько раз, и на этот раз меня это заинтриговало достаточно, чтобы спросить.

Ответы [ 9 ]

18 голосов
/ 16 января 2009

да, это совершенно безопасно и считается стандартной практикой. Строковые литералы гарантированно будут правильно обнуляться.

12 голосов
/ 16 января 2009

Вы уверены, что код не предназначен для совпадения на "--helpmedosoemthingwithareallylongoptionname"

4 голосов
/ 16 января 2009

Ты прав.

Более того, приведенный вами пример будет соответствовать «--help», но также и всему, что начинается с «--help» (как «--help-me»).

Редкий случай, когда чрезмерное усердие == неправильно.

1 голос
/ 16 января 2009

Как уже говорили другие, strcmp() совершенно безопасно для использования с литералами. Если вы хотите использовать strncmp(), попробуйте это:

strncmp(argv[i], "--help", sizeof("--help"))

Пусть компилятор сделает подсчет за вас!

Это будет соответствовать только точной строке "--help". Если вы хотите сопоставить все строки, которые начинаются с "--help" (как и ваш код), используйте sizeof() - 1, чтобы не включать последние '\0'.

1 голос
/ 16 января 2009

Насколько я знаю, вы абсолютно правы - нет причин использовать strncmp вместо strcmp. Возможно, люди просто слишком осторожны (не обязательно плохо).

0 голосов
/ 16 января 2009

э-э ... технически не могло случиться что-то подобное?

char *cp1 = "help";
cp1[4] = '!'; // BAD PRACTICE! don't try to mutate a string constant!
// Especially if you remove the terminating null!
  ...
strcmp(some_variable, "help"); 
// if compiler is "smart" enough to use the same memory to implement
// both instances of "help", you are screwed...

Полагаю, это патологический случай и / или мусор на входе ("Док, мне больно, когда я бью головой о стену!" "Тогда не делай этого!") ...

(p.s. Я просто поднимаю вопрос - если вы чувствуете, что это сообщение запачкает воду, прокомментируйте соответственно, и я удалю его)

0 голосов
/ 16 января 2009

Это, вероятно, не сделано для безопасности. Это можно было сделать, чтобы проверить только начало параметра командной строки. Многие программы просто проверяют начало переключателей командной строки и игнорируют остальные.

0 голосов
/ 16 января 2009

Я бы, вероятно, написал что-то вроде этого в C (если бы я много использовал strncmp и не хотел подсчитывать символы):

if(... strncmp(argv[i], "--help", sizeof("--help") - 1) == 0 
0 голосов
/ 16 января 2009

Да, наличие литерала ограничивает размер сравниваемых данных до размера литерала. stncmp здесь избыточен.

Некоторые могут сказать, что strncmp - это хорошая привычка, но это перевешивает проблема подсчета символов.

...