Я пишу загрузчик в C11. Когда загрузчику необходимо перенести элемент управления на прошивку, он считывает указатель на определенный предопределенный адрес памяти и вызывает его. Код выглядит следующим образом:Как использовать noreturn с указателем функции?
typedef void (FirmwareBootFn)(void);
typedef struct
{
uint32_t stackPointer;
FirmwareBootFn* programCounter;
}
FirmwareBootControl;
static FirmwareBootControl g_bootControl __attribute__ ((section (".boot_control")));
void
Firmware_boot(void)
{
setStackPointer(g_bootControl.stackPointer);
g_bootControl.programCounter();
}
Функция Firmware_boot()
никогда не возвращается, так что имеет смысл объявить его как noreturn
:
#include <stdnoreturn.h>
noreturn void
Firmware_boot(void);
Но мне нужно объявить FirmwareBootFn
, как noreturn
также, чтобы избежать компилятор жалуется, что Firmware_boot()
может вернуться.
Я пробовал (возможно) каждую перестановку noreturn
в typedef
без каких-либо результатов. Также я понял, что атрибут не может быть установлен в typedef
, потому что он не является частью этого типа.
Есть ли способ пометить мой Firmware_boot()
как noreturn
, избегая предупреждения (ну без обмана с предупреждением :-))?
Я только что нашел обходное решение для gcc: используя ** __ builtin_unreachable **() отмечает определенную точку кода, поскольку «эта строка никогда не будет выполнена», тем самым предоставив свойство noreturn. Несмотря на это, он не переносится и не позволяет компилятору понять, что (по крайней мере, IMO) g_bootControl.programCounter() не возвращается и не применяет правильную оптимизацию. – MaxP
@MaxP, как документация, так и выход ассемблера небольшой тестовой программы, похоже, указывают, что она используется для оптимизации. (Если 'foo' объявлен' _Noreturn' и 'bar' нет,' foo(); 'и' bar(); __builtin_unreachable(); 'генерировать эквивалентный код.) – mafso
Если вы хотите использовать расширение, используйте атрибут. Пожалуйста, см. Мой ответ. –