В связанном примере с исходным кодом с авторскими правами более 20 лет назад, скорее всего, библиотека времени C имеет переменную int errno;
. extern int errno;
в заголовке означает, что «эта переменная существует, вы найдете ее где-то еще» - возможно, рядом с кодом, который на самом деле вызывает вашу функцию main
или что-то подобное.
Как правило, в современной ОС с потоками errno
не является строго переменной.
Это пример в Linux, из /usr/include/bits/errno.h в glibc.
# ifndef __ASSEMBLER__
/* Function to get address of global `errno' variable. */
extern int *__errno_location (void) __THROW __attribute__ ((__const__));
# if !defined _LIBC || defined _LIBC_REENTRANT
/* When using threads, errno is a per-thread value. */
# define errno (*__errno_location())
# endif
# endif /* !__ASSEMBLER__ */
#endif /* _ERRNO_H */
как именно этого __errno_location
реализуется, зависит от того, какой вариант того, что ОС, но, по сути, это что-то вроде:
__thread int errno;
где __thread
транслирует 11 thread_local
C++ хранения спецификатор, и поддерживаемая ОС как своего рода «своп данных на поток». Именно то, как это реализовано, снова зависит от ОС. В x86 и x86-64 fs
и gs
используются для хранения «на процессор» и «на поток» (но они «против», и я не могу вспомнить, что именно сейчас)
'errno' must только ведут себя как глобальный 'int'. На самом деле он не должен определяться как таковой, обычно это макрос, который возвращает значение lvalue, например '#define errno (* (int *) getErrnoPtr()) или что-то в этом роде. Почему вас интересует конкретное определение? – mtijanic
Тот же ответ, что и 'printf' объявлен (неявно как extern), и мы можем назвать его, поэтому где он определен? – immibis
Вероятно, он выделяется, как и на самом деле, в заголовке стека потоков. Это «местоположение» - это определение ОС/архитектуры и, поскольку оно должно быть зависимым от потока, заголовок стека будет казаться очевидным местом для ОС. –