Сравнение двух строковых литералов с использованием memcmp
Я сравнил два строковых литерала, используя memcmp
функция.
#include <stdio.h>
#include <string.h>
int main()
{
char str1[] = "abcd";
char str2[] = "ab";
if (memcmp(str1, str2, 4) == 0)
{
printf("equal string\n");
}
return 0;
}
В вышеуказанной программе str2
короче чем str1
, Это означает строку str2
доступ за пределы.
Итак, это неопределенное поведение?
2 ответа
Поведение вашего кода не определено. Стандарт С не требует, чтобы memcmp
возвращается, как только результат известен; то есть не обязательно возвращаться, когда \0
по сравнению с 'c'
несмотря на ценность 'c' == '\0'
являющийся 0
для любой кодировки символов, поддерживаемой языком. Стандарт также не определяет порядок, в котором должны проводиться лексикографические сравнения (хотя было бы сложно, чтобы реализация не начиналась с самого начала).
str2
это char[3]
тип. Возможно, сделана попытка доступа к 4-му элементу.
Да, поведение вашего кода не определено. Тем не менее, пока вы используете if (memcmp(str1, str2, 3) == 0)
(обратите внимание, что число байтов равно 3 вместо 4. Т.е. как минимум два), поведение вашего кода будет приемлемым и правильным.
Поведение не определено, если доступ происходит после конца любого объекта, на который указывают lhs и rhs. Поведение не определено, если lhs или rhs является нулевым указателем.
В случае strcmp он останавливается, как только находит \0
, Тем не менее, для memcmp,
ошибочное предположение, что memcmp сравнивает побайтово и не смотрит на байты за пределами первой точки различия. Функция memcmp не дает такой гарантии. Разрешается читать все байты из обоих буферов, прежде чем сообщать о результате сравнения.
Итак, я бы написал свой код так:
#include <stdio.h>
#include <string.h>
#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
int main()
{
char str1[] = "abcd";
char str2[] = "ab";
int charsToCompare = MIN(strlen(str1), strlen(str2)) + 1;
if (memcmp(str1, str2, charsToCompare) == 0)
{
printf("equal string\n");
}
return 0;
}
Более подробная информация и анализ memcmp
можно найти здесь.