Jub*_*ian 5 c pointers memory-address
有些架构具有多个地址空间,著名的例子是真正的哈佛架构,但 OpenCL 也具有此属性。
C 编译器可能为此提供一些解决方案,其中之一是命名地址空间,支持特殊的指针限定符来指示指针的地址空间,但也可能存在其他解决方案。
我不知道它们,并且在我使用的架构(8 位 AVR)上,还有另一种解决方案来处理该问题,即专门的宏 ( )pgmspace.h来处理 ROM 中的数据。但是对这些没有类型检查,并且它们(在我看来)使代码变得丑陋,所以在我看来,使用命名地址空间是一种更好的,甚至可能更便携的方式来处理问题(可移植的通过为地址空间限定符提供空定义,可以轻松地将这样的软件移植到具有单个地址空间的目标。
然而,在我从其可用性中了解到的上一个问题中,建议使用命名地址空间的解决方案被严重否决,此处:如何使两个其他相同的指针类型不兼容
反对者没有提供任何解释,我自己也没有找到任何解释,对我来说,命名地址空间似乎是处理问题的一种很好且功能完善的方式。
有人能提供解释吗?为什么不应该使用命名地址空间?(倾向于具有多个不同地址空间的目标上可用的任何其他方法)
这些问题很明显:它们只适用于 gcc 编译器。
在嵌入式系统分支中,有许多不同的编译器,每个编译器都提供自己独特的、不可移植的方式来执行此操作。有时这很好(大多数嵌入式项目永远不会移植到不同的编译器),但从一般的角度来看,事实并非如此。
(扩展地址也存在同样的问题 - 例如,如果您使用具有超过 64kib 可寻址内存的 8 或 16 位 MCU。然后编译器使用各种非标准扩展,例如near和far。)
这些问题的一种解决方案是围绕编译器特定的行为制作一个“包装器”,方法是制作一个硬件抽象层 (HAL),在其中指定用于在闪存中存储数据的类型或flash_byte_t类似类型,然后从 HAL 中包含包含实际 typedef 的编译器特定头文件,例如typedef const __flash uint8_t flash_byte_t;. 例如,应用程序包含“compiler.h”,而该应用程序又包含“gcc.h”。这样当你切换编译器时你只需要重写一个小头文件。
事实证明,C 也允许const flash_byte_t这样,即使这已经被 typedef 为 const。C 中有一个特殊的奇怪规则,即您可以根据需要在声明中多次添加相同的限定符。所以const const int x相当于const int x. 这意味着如果用户添加额外的 const 限定,那就没问题。
请注意,这里主要是 AVR 是一个特殊的例外,因为它有奇怪的哈佛模型。
否则,大多数编译器都会使用一个行业事实上的标准约定:所有const具有静态存储持续时间的合格变量都应分配在闪存中。当然,C 标准对此不做任何保证(这超出了标准的范围),但大多数嵌入式编译器的行为都是如此。