В чем заключается вышеуказанная декларация, объявляется функция extern
с именем my_main()
без аргументов.
Раздел __attribute__
является GNU/LLVM attribute syntax. Атрибуты - это в основном прагмы, описывающие нестандартную или расширенную функцию рассматриваемой функции - в данном случае - my_main()
.
К my_main()
относятся два атрибута.
__noreturn__
(поиск по noreturn
) указывает, что функция будет никогда возвращение.
Это отличное от возврата void
- в void
-type функции, вызовы функции все еще return
в какой-то момент, даже без значения. Это означает, что выполнение будет возвращаться/возвращаться к вызывающему абоненту.
В noreturn
(ака _noreturn
или __noreturn__
) функций, это указывает на то, что, среди прочего, требует, чтобы эту функцию не следует добавить адрес возврата в стек, как функция сама будет либо выйти из программы возвращения исполнения, или будет длинный переход к другой точке исполнения.
Он также используется в тех местах, где добавление обратного адреса в стек приведет к нарушению стека таким образом, что это помешает вызываемой функции (хотя это редко, и я только когда-либо видел, что это использовалось по этой причине один раз) ,
Второй атрибут, asection(".main","f=ax")
, немного более расплывчатым. Кажется, я не могу найти конкретную документацию, но кажется более или менее довольно простой.
Что это, кажется, делает это указание на linker section, а также то, что появляется быть unix filemode указав, что в результате двоичный E х ecutable, хотя я могу ошибаться.
При написании собственного кода, все функциональные возможности помещены в соответствующие разделы целевого двоичного формата (например, ELF, Маха-O, PE и т.д.) Наиболее распространенные секции .text
, .rodata
и .data
.
Однако при вызове ld
, компоновщик GCC, вы можете указать linker script указать точно как вы хотите целевой двоичный будет построен.
Сюда входят разделы, размеры и даже файлы объектов, которые вы хотите использовать для создания файла, указав, куда они должны идти, и их пределы размера.
Одним из распространенных заблуждений является то, что вы никогда не используете ld
. Это не так; при запуске gcc
или g++
или clang
-семейком компиляторов без флага -c
, вы непреднамеренно вызываете ld
с помощью default linker script, используемого для связи ваших двоичных файлов.
Сценарии компоновщика важны, особенно для встроенных аппаратных средств, где ПЗУ должно быть создано для спецификации памяти.
Итак, вернемся к вашей строке кода: он помещает my_func()
в произвольный раздел под названием .main
. Это все, что он делает. В конечном счете, где-то в вашем проекте есть сценарий компоновщика, который указывает, как используется .main
и где он идет.
Я предположил бы, что цель этого кода в том, чтобы разместить my_main()
на точный адрес в целевом двоичном/исполняемый файл, поэтому все, что использует его знает точное местонахождение этой функции (asection(".main")
) и может использовать его в качестве точка входа (__noreturn__
).
Не могли бы вы указать используемый компилятор/идеал? – Superlokkus
Это сложно для anser, не зная больше о платформе, которую вы используете/программируете. –
это функция void, объявленная атрибутами функции. [Читать здесь] (https://gcc.gnu.org/onlinedocs/gcc-3.2.1/gcc/Function-Attributes.html) – Michi