2015-02-26 12 views
10

Tôi đang viết bộ nạp khởi động trong C11. Khi bộ tải khởi động cần truyền điều khiển đến phần sụn, nó sẽ đọc một con trỏ hàm tại địa chỉ bộ nhớ được xác định trước và gọi nó. Mã này trông như thế này:Làm thế nào để sử dụng noreturn với con trỏ hàm?

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(); 
} 

Chức năng Firmware_boot() không bao giờ trở lại, vì vậy nó làm cho tinh thần để khai báo nó như noreturn:

#include <stdnoreturn.h> 

noreturn void 
Firmware_boot(void); 

Nhưng tôi cần phải khai báo FirmwareBootFn như noreturn cũng như để tránh các trình biên dịch phàn nàn rằng Firmware_boot() có thể trở lại.

Tôi đã thử (có thể) mọi hoán vị của noreturn trong số typedef mà không có bất kỳ kết quả nào. Ngoài ra tôi hiểu rằng thuộc tính không thể được đặt trong typedef bởi vì nó không phải là một phần của loại.

Có cách nào để gắn thẻ số Firmware_boot() của mình là noreturn tránh cảnh báo (tốt mà không bị gian lận với ngăn chặn cảnh báo :-)) không?

+0

Tôi chỉ tìm thấy giải pháp thay thế cho gcc: sử dụng ** __ builtin_unreachable **() đánh dấu một điểm cụ thể của mã là "dòng này sẽ không bao giờ được thực hiện" do đó cấp thuộc tính noreturn. Mặc dù công trình này, nó không phải là di động và không cho phép trình biên dịch để hiểu rằng (ít nhất là IMO) g_bootControl.programCounter() không trở lại và áp dụng tối ưu hóa thích hợp. – MaxP

+1

@MaxP, cả tài liệu và đầu ra của trình biên dịch của một chương trình thử nghiệm nhỏ dường như chỉ ra nó được sử dụng để tối ưu hóa. (Nếu 'foo' được khai báo' _Noreturn' và 'bar' không phải là' foo(); 'và' bar(); __builtin_unreachable(); 'tạo mã tương đương.) – mafso

+0

Nếu bạn sẵn sàng sử dụng phần mở rộng, sử dụng một 'thuộc tính'. Xin vui lòng xem câu trả lời của tôi. –

Trả lời

6

_Noreturn trong C11 chỉ có thể được áp dụng cho định nghĩa chức năng hoặc khai báo. Thực tế là chức năng không trả lại không phải là một phần của nguyên mẫu, thật không may.

Vì bạn dường như có gcc bạn có thể sử dụng một phần mở rộng

typedef struct 
{ 
    uint32_t stackPointer; 
    __attribute__((__noreturn__)) FirmwareBootFn* programCounter; 
} 
FirmwareBootControl; 

để đánh dấu con trỏ hàm như không trở về. Thật không may mặc dù, có vẻ không phải là một cách để đảm bảo rằng các chức năng mà bạn gán cho rằng thực sự có tài sản đó bằng cú pháp, allone.

Các vấn đề liên quan