Ответ 1
Скорее всего, вы видите результат оптимизации компилятора. Если мы проверим код с помощью gcc на godbolt, с уровнем оптимизации -O0
, мы можем видеть, что в первом случае он не вызывает strcmp
movl $-1, %esi #,
movl $.LC0, %edi #,
movl $0, %eax #,
call printf #
Поскольку вы используете константы в качестве аргументов strcmp, компилятор может выполнять постоянная сворачивание и вызовите компилятор intrinsic во время компиляции и сгенерируйте -1
, а затем вместо вызова strcmp
во время выполнения, которое реализовано в стандартной библиотеке и будет иметь другую реализацию, а затем более вероятное время компиляции strcmp
.
Во втором случае он вызывает вызов strcmp
:
call strcmp #
movl %eax, %esi # D.2047,
movl $.LC0, %edi #,
movl $0, %eax #,
call printf #
Это согласуется с тем фактом, что gcc имеет встроенный файл для strcmp, что будет использоваться gcc
при постоянном складывании.
Если мы еще тест с использованием -O1
уровня оптимизации или выше gcc
может сбрасывать оба случая, и результат будет -1
для обоих случаев:
movl $-1, %esi #,
movl $.LC0, %edi #,
xorl %eax, %eax #
call printf #
movl $-1, %esi #,
movl $.LC0, %edi #,
xorl %eax, %eax #
call printf #
При увеличении числа опций оптимизации оптимизатор может определить, что a
и b
указывают на константы, известные также во время компиляции, а также могут вычислять результат strcmp
для этого случая также во время компиляции.
Мы можем подтвердить, что gcc
использует встроенную функцию, создавая с - fno-builtin flag и отмечая, что вызов strcmp
будет генерироваться для всех случаев.
clang
немного отличается тем, что он вообще не складывается при использовании -O0
, но будет складываться при -O1
и выше для обоих.
Обратите внимание, что любой отрицательный результат является полностью совместимым, мы можем видеть, перейдя в проект стандартного раздела C99 7.21.4.2
Функция strcmp, которая говорит (выделение мое):
int strcmp(const char *s1, const char *s2);
Функция strcmp возвращает целое число, большее, чем, или меньше чем нуль, соответственно, поскольку строка, на которую указывает s1, больше, чем, равно или меньше, чем строка, на которую указывает s2.
technosurus указывает, что strcmp
указан для обработки строк, как если бы они были составлены из unsigned char, это описано в C99 под 7.21.1
, в котором говорится:
Для всех функций в этом подпункте каждый символ должен быть интерпретируется так, как будто у него был тип unsigned char (и, следовательно, каждый возможное представление объекта допустимо и имеет другое значение).