我有一个构建引导加载程序的任务,该加载程序虽然很成功,但引发了所有重要问题,说明其为何有效。通过它,我陷入了两行非常相似的代码中。
//Get the application stack pointer (1st entry in the application vector table)
appStack = (uint32_t) *((__IO uint32_t*) APPLICATION_ADDRESS);
//Get the application entry address (2nd entry in the application entry table)
appEntry = (pFunction) *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
我已经定义了APPLICATION_ADDRESS
。我已将pFunction
定义为一个函数的指针。这是我的理解尝试:
(忽略__IO
,因为这仅意味着volatile
)
(__IO uint32_t*) APPLICATION_ADDRESS)
将APPLICATION_ADDRESS
强制转换为一个指针,该指针返回32位无符号整数。这意味着,如果我们转到地址APPLICATION_ADDRESS
,将有一个存放uint32_t
的存储位置的另一个地址。
在*((__IO uint32_t *) APPLICATION_ADDRESS)
中,我们使用解引用运算符来获取APPLICATION_ADDRESS
所指向的值。 APPLICATION_ADDRESS
指向另一个包含将返回值的地址。然后(uint32_t)
将此值强制转换为uint32_t
。
按照我的理解,由于您已经说过括号中的变量为uint32_t
,因此转换变得多余。
这与我对下一行的理解相矛盾。为什么我们最初没有将APP_ADDRESS + 4
定义为pFunction
?
最后,我对方括号排列的差异感到困惑。为什么取消引用运算符不会像这样包围整个int_32
和(APPLICATION_ADDRESS +4)
:
*((__IO uint32_t*) (APPLICATION_ADDRESS + 4))
还是用括号括起来的过度杀伤力,只是不是必需的?
答案 0 :(得分:3)
您有一些正确的假设和一些错误的假设。
您似乎在内存中的固定位置存储了2个值:
APPLICATION_ADDRESS + 0 +----------------------+
| Stack |
+ 4 +----------------------+
| pFunction |
+ 8 +----------------------+
现在让我们看看您的假设:
(__IO uint32_t*) APPLICATION_ADDRESS)
将APPLICATION_ADDRESS
强制转换为 返回32位无符号整数的指针。
是的,正确。
这意味着,如果我们转到地址
APPLICATION_ADDRESS
,将会有另一个 存放uint32_t的内存位置的地址。
关闭但不正确。
在位置APPLICATION_ADDRESS
处,您找不到另一个整数地址,但在其中找到了所述整数本身。
在*((____ uint32_t *)APPLICATION_ADDRESS)中,我们使用取消引用 运算符以获取
APPLICATION_ADDRESS
指向的值。
是的。
好吧,有点古怪,APPLICATION_ADDRESS
并不指向任何地方。它只是一个普通数字,而不是指针。这就是为什么您需要对各种指针类型进行所有强制类型转换的原因。
APPLICATION_ADDRESS
指向另一个包含值的地址 这将被退回。然后(uint32_t)
将此值强制转换为uint32_t
。
否,APPLICATION_ADDRESS
是该整数的地址。
按照我的理解,将演员表冗余为 您已经说过,所保存的变量是uint32_t 括号。
正确。
这与我对下一行的理解相矛盾。为什么没有 我们将
APP_ADDRESS + 4
定义为方括号内的pFunction 最初?
从整数到指针的转换取决于实现。函数地址甚至更多。如果将内存内容定义为32位整数,则必须使用该类型读取它。然后,您可以根据需要进行任何转换。 这可能只会导致相同的值,也可能会有所不同。这取决于架构。
最后,我对方括号排列的差异感到困惑。 为什么取消引用运算符不包围整个
int_32
并(APPLICATION_ADDRESS +4)
像这样:*((__IO uint32_t*) (APPLICATION_ADDRESS + 4))
还是用括号括起来的过度杀伤力,只是不是必需的?
不需要外部括号。 内括号很重要。没有括号,演员表将优先于加法。然后,您将不会在地址中添加4个字节,而是在此处添加4个内存对象的大小,即16个字节。