这部分代码的含义是什么?

时间:2016-11-15 10:17:58

标签: c++ c

有人能说出这段代码的含义是什么吗?

void (* const rvt[])(void) = {
  (void (*) (void))((unsigned long)&__STACK_END), // The initial stack pointer
  xkg_som,                                  // The reset handler
  xnt_ISR,                                  // The NMI handler
  FaultISR,                                 // The hard fault handler
  IntDefaultHandler,                        // The MPU fault handler
  bgs_stm,                                  // The bus fault handler
  IntDefaultHandler,                        // The usage fault handler
  0,                                        // Reserved
  0,                                        // Reserved
  IntDefaultHandler,                        // The MPU fault handler
};

我其实不明白。

4 个答案:

答案 0 :(得分:8)

void (* const rvt[])(void)

手段(由cdecl.org提供):

  

声明rvt为const指针的函数(void)返回void

T foo = {
    value1,
    value2,
    value3 // ...
};

这是数组的aggregate initialization [1]。此外,这意味着rvt的声明是一个定义。

&__STACK_END

addresof运算符获取变量的内存地址。

(unsigned long)&__STACK_END)

地址已投放到unsigned long类型。

(void (*) (void))((unsigned long)&__STACK_END)

转换后的值再次转换为指向函数(void)的指针返回void,这是存储在数组中的函数指针的类型。

数组的其余初始化值可以是函数名,函数指针,也可以是隐式转换为函数指针的函数,如lambdas。

答案 1 :(得分:3)

void (* const rvt[])(void)

这定义了一个名为" rvt"的const数组。它的元素是一个没有参数的void函数的指针。

然后使用大括号初始化列表初始化此数组。所以其他所有行都是这个数组的元素。第一个是指向__STACK_END的指针,它显然是错误的类型,因此需要被转换为正确的类型(它将首先被转换为无符号长整数然后进入正确的函数类型指针)。

Btw:代码不完整,因为大括号没有关闭,或者格式化错误,因为最后一条评论包含右括号?

答案 2 :(得分:1)

它定义了一个指向函数的指针数组,它不带参数并返回void。然后使用内存中某些寄存器的地址初始化数组,这些寄存器被转换为函数指针。

看起来像用于嵌入式编程的中断向量表。

答案 3 :(得分:0)

这似乎是ARM Cortex M微控制器的中断向量表。

enter image description here

与大多数其他MCU相比,ARM Cortex的一个特殊功能是它在程序启动之前设置了堆栈指针。其他MCU倾向于在运行时设置它。

因此,表中的第一个条目是在程序启动时堆栈指针应设置的值。 __STACK_END可能是从链接器获得的常量。强制转换(void (*) (void))将其转换为函数指针。从指向int的指针转换为函数指针有点值得怀疑,但它可能适用于大多数嵌入式C编译器,尽管C标准不满意。

其余条目是用于中断服务例程(函数)的函数地址。也就是说,它们与函数指针是一样的。您可以通过为函数指定名称来初始化函数指针。

因此,整个向量表被声明为函数指针数组,其中每个函数都具有签名void func (void)*const声明意味着函数指针本身是只读的。这意味着它们将在flash中分配,这对于向量表是合适的。向量表通常分配在flash中固定的保留地址。

编写相同代码的更漂亮的方法是:

typedef void (isr_t)(void);

isr_t* const [] = {
  (isr_t* const)((uintptr_t)&__STACK_END),  // The initial stack pointer
...

uintptr_t是一个足够大的整数类型,保证能够保存地址,与unsigned long不同。