我在嵌入式目标上工作,并希望定义内存池。
内存地址表示为void*
。但是在特定情况下,这些地址被缓存,我想要解除它们以直接获得“真正的”硬件地址。
我想定义memory_area
开头的地址(这只是一个标记):
#define UNCACHE_MASK 0xABCDEF12UL // Value of the mask to apply
extern uint32_t memory_area; // Global, defined somewhere else
const void * virtual_address = &memory_area; // OK
const void * real_address =
(void*)(virtual_address | UNCACHE_MASK); // guilty line
不幸的是,GCC
不允许我这样做:
error: invalid operands to binary | (have 'const void *' and 'long unsigned int')
绝望中我试过:
const void * real_address =
(void*)(((uint32_t)virtual_address) | UNCACHE_MASK); // guilty line
徒劳:
error: initializer element is not constant
我真的想保留const
以确保安全:它是否可以实现?
[编辑]
gcc
v4.9(带-std=gnu99
和许多-Wxxx
标志)。.h
文件,变量是“全局”。答案 0 :(得分:5)
只需进行定义即可。它不会被意外改变。
#define real_address ( (void*)( (uint32_t)virtual_address | UNCACHE_MASK ) )
每次使用额外的指令或两次不是很贵。
还要在virtual_address
变量中添加一个const关键字,因此无法更改。
const void* const virtual_address = ...
答案 1 :(得分:2)
您可以使用函数内的按位OR表达式来指定它。你不能像你所示的那样在全局范围内进行初始化,因为编译器确实不知道这个值(可能在C ++中,但在C中却没有)。如果添加强制转换并在函数范围内移动赋值,它将起作用。
当你这样说时:
const void * real_address
这意味着" real_address是指向未知类型的常量内存的指针。"如果您希望指针也不可修改(除了它指向的内容),您可以这样做:
const void * const real_address
但是,您无法根据需要在函数内初始化它。我想你可以抛弃函数内部的常量,但这在C语言中可能不合法。