Сравнение int8_t и char* с использованием strcmp/strncmp

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

У меня есть две переменные: int8_t foo[size] и const char* const bar.

Есть if, который проверяет if(0 != strcmp((char *)foo, bar))

В настоящее время это не удается, хотя printf("%s | %s", foo, bar) возвращает две одинаковые строки. Я также пробовал strncmp, который также терпит неудачу.

Изучив онлайн-исследования, я понимаю, что это, скорее всего, связано с завершением нулевых байтов, однако я не понимаю, как бы я решил/обошел это.

int8_t foo[size];
const char* const bar;

if(0 != strcmp((char *)foo, bar)){
   fail 
}

Ожидаемые результаты strcmp возвращают 0, потому что обе строки одинаковы при печати.

Фактический результат: возврат не выполнен.

Фактические данные: 5352A565712345657567565785658956581
При запуске printf("Value of foo and bar: %s and %s", foo, bar) обе переменные возвращают указанные выше данные.


person Shox2711    schedule 30.01.2019    source источник
comment
Опубликуйте минимально воспроизводимый пример   -  person Eugene Sh.    schedule 30.01.2019
comment
Мы не можем ответить, не зная точно, какие данные содержатся в двух переменных.   -  person interjay    schedule 30.01.2019
comment
Если вам нужны (строки) символов, используйте char. Если вам нужны небольшие целые числа, используйте int8_t или uint8_t (или signed char или unsigned char).   -  person mlp    schedule 30.01.2019
comment
Добавил данные по запросу.   -  person Shox2711    schedule 30.01.2019
comment
А как насчет непечатаемого контента? Вы можете быть уверены, что их нет?   -  person Gerhardh    schedule 30.01.2019
comment
Если бы речь шла об окончании 0 байтов, вы должны получить один вывод длиннее другого.   -  person Gerhardh    schedule 30.01.2019
comment
@Gerhardh вот где я немного запутался (все еще новичок в C). Как я узнаю, есть ли контент, не предназначенный для печати, или это лишний вопрос?   -  person Shox2711    schedule 30.01.2019
comment
Вы можете запустить программу в отладчике и проверить содержимое памяти при входе в эту функцию.   -  person Gerhardh    schedule 30.01.2019
comment
Сравнить не удается, потому что две строки не совпадают. поскольку обе строки одинаковы, это неверный вывод с вашей стороны. Вам нужно опубликовать больше доказательств/кода, как вы (ошибочно) пришли к выводу, что это одна и та же строка.   -  person chux - Reinstate Monica    schedule 30.01.2019


Ответы (2)


недостаточно иметь:

int8_t foo[] = { 'a', 'b' };

уметь делать

if (strcmp(foo, "ab") == 0)
  puts("equals");
else
  puts("not equal");

потому что strcmp, как и многие другие функции, работающие с char *, ожидают нулевой символ, сигнализирующий о конце строки.

То, что добавляется, когда strcmp идет после 'b' в foo, является неопределенным поведением

so

int8_t foo[] = { 'a', 'b', 0 };

является кандидатом на strcmp(foo, "ab") благодаря добавленному нулевому символу, позволяющему strcmp не выходить за пределы foo в любых случаях


Обратите внимание, что та же проблема возникает, если вы делаете printf("%s", foo); в первом случае, в то время как нулевой символ не достигается в памяти после 'b' из foo функция printf попытается для записи памяти в виде символов, но это поведение undefined

person bruno    schedule 30.01.2019
comment
Отличный ответ, спасибо, что нашли время, чтобы сделать его вполне понятным! Просто быстрый дополнительный вопрос, foo, будучи инициализированным int8_t foo[size], передается в функцию x(foo). Эта функция заполняет массив из операторов sqlite3. Как мне добавить нулевой терминатор к foo после того, как он будет заполнен его значениями? - person Shox2711; 31.01.2019
comment
Не обращая внимания на приведенный выше комментарий, я добавил массивы с нулевым терминатором 0 и все еще не работает. Однако, когда я печатаю foo и bar как шестнадцатеричные числа (%x), они разные. foo = vcd16a40 и бар = vcd169e0 - person Shox2711; 31.01.2019
comment
@CianO'Shaughnessy функция x должна помещать нулевой байт в конец или, например, возвращать количество байтов, установленных для возможности добавления нуля в нужное положение. Однако смешивать строку и массив байтов довольно странно ;-) - person bruno; 31.01.2019
comment
@CianO'Shaughnessy, как у вас может быть «v» в гексагоне? int8_t foo[] = { 'a', 'b', 0 }; printf("%d\n", strcmp(foo, "ab")); напечатает 0 - person bruno; 31.01.2019

Я не могу воссоздать этот сценарий, несмотря на получение предупреждений во время компиляции. Каково ожидаемое поведение? Вы имеете в виду, что сравнение не работает, или код не может попасть в блок if? Если оба массива содержат одинаковые данные, strcmp() вернет 0, и тогда блок if не будет выполнен.

Я просто пытаюсь уточнить. ответ Бруно, учитывая поведение strcmp, также верен.

person Michał Stoń    schedule 30.01.2019