Strcmp() и подписанные /unsigned символы
Я запутался в strcmp(), точнее, как он определяется стандартом. Рассмотрим сравнение двух строк, в которых содержатся символы вне диапазона ASCII-7 (0-127).
Стандарт C определяет:
int strcmp (const char * s1, const char * s2);
Функция strcmp сравнивает строку, на которую указывает s1, на строку на который указывает s2.
Функция strcmp возвращает целое число, большее, равное или меньше нуля, соответственно, как строка, на которую указывает s1, больше чем, равный или меньше, чем строка, на которую указывает s2.
Параметры char *
. Не unsigned char *
. Нет понятия, что "сравнение должно выполняться как unsigned
".
Но все стандартные библиотеки, которые я проверил, рассматривают "высокий" символ как раз тот, который выше по значению, чем символы ASCII-7.
Я понимаю, что это полезно и ожидаемое поведение. Я не хочу сказать, что существующие реализации ошибочны или что-то в этом роде. Я просто хочу знать, , какая часть стандартных спецификаций я пропустил?
int strcmp_default( const char * s1, const char * s2 )
{
while ( ( *s1 ) && ( *s1 == *s2 ) )
{
++s1;
++s2;
}
return ( *s1 - *s2 );
}
int strcmp_unsigned( const char * s1, const char *s2 )
{
unsigned char * p1 = (unsigned char *)s1;
unsigned char * p2 = (unsigned char *)s2;
while ( ( *p1 ) && ( *p1 == *p2 ) )
{
++p1;
++p2;
}
return ( *p1 - *p2 );
}
#include <stdio.h>
#include <string.h>
int main()
{
char x1[] = "abc";
char x2[] = "abü";
printf( "%d\n", strcmp_default( x1, x2 ) );
printf( "%d\n", strcmp_unsigned( x1, x2 ) );
printf( "%d\n", strcmp( x1, x2 ) );
return 0;
}
Выход:
103
-153
-153
Ответы
Ответ 1
7.21.4/1 (C99), акцент мой:
Знак ненулевого значения, возвращаемого функциями сравнения memcmp, strcmp, и strncmp определяется знаком разности между значениями первого пара символов (, интерпретируемых как unsigned char), которые отличаются тем, что объекты по сравнению.
В C90 есть что-то подобное.
Обратите внимание, что strcoll() может быть более адаптирован, чем strcmp(), особенно если у вас есть символ вне базового набора символов.