TL; DR;
Возможно, вам не удастся принудительно ввести значение в единицу компиляции, но вы можете применить символ, определив глобальную переменную в заголовке. т.е.: long using_my_library_version_1_2_3;
Символ будет доступен извне в конечном двоичном файле и может быть проверен (хотя, как и любое решение, его можно обойти, не говоря уже о том, что сам заголовок можно изменить).
РЕДАКТИРОВАТЬ : Чтобы уточнить (из-за комментариев), не используйте переменную static
.
При использовании глобальной переменной по умолчанию она будет extern
и не будет оптимизирована (в случае, если другие объекты, загружающие двоичный файл, используют идентификатор).
Предостережения и пример:
Как уже упоминалось в комментариях, идентификатор (имя) глобальной переменной - это строка в этом подходе.
Однако при компиляции исполняемых файлов (и ядер) идентификаторы могут быть удалены из окончательного двоичного файла при компиляции с (-s
). Это часто делают разработчики встроенных систем и люди, которым нравится делать отладку живым адом (даже больше, чем в любом случае).
Быстрый пример:
// main.c
int this_is_example_version_0_0_1; /* variable name will show in the file */
int main(void) {
/* placed anywhere to avoid the "not used" warning: */
(void)this_is_example_version_0_0_1;
return 0;
}
// extra.c
int this_is_example_version_0_0_1; /* repeat line to your heart's content */
int this_is_example_version_0_0_1; /* (i.e., if header has no include guard) */
Компиляция:
$ cc -xc -o a -Wall -O2 main.c extra.c
Список всех идентификаторов / имен (будет отображаться глобально):
nm ./a | grep "this_is_example_version"
Проверка строки в двоичном файле с использованием:
$ grep -F "this_is_example_version" ./a
подробности:
Забавные факты о C, которые делают возможным это решение ...:
C определяет extern
как значение по умолчанию для объявлений функций и переменных в глобальной области (6.2.2, подраздел 5).
В соответствии с разделом 6.2.2 («Связи идентификаторов») «каждое объявление определенного идентификатора с внешней связью обозначает один и тот же объект или функцию».
Это означает, что дубликаты объявлений в глобальной области видимости будут сопоставляться с одной декларацией.
Объявления переменных и определения переменных выглядят одинаково, когда переменная помещается в глобальную область и все ее биты установлены в ноль.
Это потому, что глобальные переменные по умолчанию инициализируются нулями. Следовательно, компиляторы не могут определить, является ли int foo;
определением (int foo = 0;
) или объявлением (extern int foo;
).
Из-за этой "идентичности" и этих правил компиляторы преобразуют неоднозначные объявления / определения глобальных переменных в "слабые" объявления, которые должны разрешаться компоновщиком.
Это означает, что если вы определяете глобальную переменную без ключевого слова extern
и без значения, неоднозначное объявление / определение заставит компилятор выдавать слабый символ, который будет выставлен в окончательном двоичном файле.
Этот символ может использоваться для идентификации того факта, что заголовок использовался где-то в программе.