fk0, легенда (15.01.2013 14:52, просмотров: 3074)
Говнокод нового уровня. Хочу понять, оно в принципе имеет право на жизнь или нет (для GCC): В модуле file1.c делаем:
const unsigned __NONAMED __attribute__((weak,section("NAME"))) = 521;
В модуле file2.c делаем:
const unsigned __NONAMED __attribute__((weak,section("NAME"))) = 354;
В модуле file3.c, file4.c... и т.п. делаем аналогично. Только циферки везде разные, но их значение -- принципиально важно.
В очередном модуле main.c, делаем:
int main()
{
const unsigned N=__stop_NAME-__start_NAME;
unsigned i;
for (i=0; i<N; i++) {
ИСПОЛЬЗУЕМ_ЧИСЛА(__start_NAME[i]);
}
...
return 0;
}
Компилятор для каждой секции NAME создаёт __start_NAME и __stop_NAME (начиная с каких-то версий GCC, если не создаёт -- объяснили ему это делать через скрипт для линкера).
То-есть в чём суть. weak для всех __NONAMED позволяет обойти ошибку мол multiple definitions of один symbol in разные modules. Но при этом в область памяти соответствующей секции NAME все числа присвоенные множественным переменным __NONAMED попадают и их можно перебрать зная начало и конец секции.
Может здесь какой-то косяк, который я в упор не вижу?
Зачем это надо. Это позволяет решение принципиальной задачи: определить что-то в разных модулях, что между собой никак иначе не пересекается (не перечисляется где-то в третьем модуле, где можно попросту забыть перечислить). И потом использовать. Например реализовать вызов конструкторов а-ля C++, для конструктора достаточно только через макрос поместить ссылку на него в секцию NAME, без непосредственной ссылки из какого-то третьего C-файла.
Зачем weak -- иначе все имена __NONAMED должны быть разные (что сложно обеспечить, даже через __LINE__, потому, что последний вполне может совпасть в разных модулях). Статическими __NONAMED быть не могут (без обращения к ним их компилятор выкинет), только глобальными.
Насколько это реализуемо в других компиляторах? Без weak придётся, например, в каждом случае выдумывать вручную разные имена, непересекающиеся в разных модулях. Без возможности положить в нужную секцию -- делать asm("section, blablabla"). Что невозможно для сложных структур данных, но в простых случаях вполне терпимо. Больше ничего в голову не приходит.
[ZX]