Контекст: в недавнем разговоре вопрос "gcc / clang делает strlen("static string")
во время компиляции?"подошел.После некоторого тестирования ответ, кажется, да, независимо от уровня оптимизации.Я был немного удивлен, увидев, что это сделано даже в -O0
, поэтому я провел некоторое тестирование и в итоге пришел к следующему коду:
#include <stdio.h>
unsigned long strlen(const char* s) {
return 10;
}
unsigned long f() {
return strlen("abcd");
}
unsigned long g(const char* s) {
return strlen(s);
}
int main() {
printf("%ld %ld\n",f(),g("abcd"));
return 0;
}
К моему удивлению, он печатает 4 10
, а не 10 10
.Я попытался скомпилировать с gcc
и clang
, а также с различными флагами (-pedantic
, -O0
, -O3
, -std=c89
, -std=c11
, ...), и поведение между тестами было согласованным.
Поскольку я не включил string.h
, я ожидал, что будет использовано мое определение strlen
.Но код сборки действительно показывает, что strlen("abcd")
был в основном заменен на return 4
(что я наблюдаю при запуске программы).
Кроме того, компиляторы не выводят предупреждений с помощью -Wall -Wextra
(большеточно, ни один не связан с проблемой: они все еще предупреждают, что параметр s
не используется в моем определении strlen
).
Возникают два (связанных) вопроса (я думаю, что они достаточно связаны, чтобы быть заданными втот же вопрос):
- разрешено ли переопределять стандартную функцию в C, если заголовок объявляет, что она не включена?
- эта программа ведет себя так, как должна?Если так, что именно происходит?