C 如何将掩码应用于常量void*地址?

C 如何将掩码应用于常量void*地址?,c,casting,memory-address,C,Casting,Memory Address,我在一个嵌入式目标上工作,希望定义内存池 内存地址表示为void*。然而,在特定情况下,这些地址是缓存的,我想取消缓存以直接获得“真实”的硬件地址 我想定义内存\u区域开头的地址(它只是一个标记): 不幸的是,GCC不允许我这样做: error: invalid operands to binary | (have 'const void *' and 'long unsigned int') 在绝望中,我试着: const void * real_address = (void*)

我在一个嵌入式目标上工作,希望定义内存池

内存地址表示为
void*
。然而,在特定情况下,这些地址是缓存的,我想取消缓存以直接获得“真实”的硬件地址

我想定义
内存\u区域
开头的地址(它只是一个标记):

不幸的是,
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
我真的很想保持
常数
以确保安全:这是可以实现的吗

[编辑]

  • 我在Linux上使用的是
    gcc
    v4.9(带有
    -std=gnu99
    和许多
    -Wxxx
    标志)
  • 摘录自
    .h
    文件,变量为“全局”

您可以使用函数中的按位或表达式来分配该值。您不能像您所示的那样在全局范围内进行初始化,因为实际上编译器不知道这个值(可能是在C++中,而不是在C中)。如果您添加强制转换并将赋值移动到函数范围内,它将起作用

当你这么说的时候:

const void * real_address
这意味着“real_address是指向未知类型的常量内存的指针”。如果您希望指针也不可修改(除了它指向的内容之外),可以执行以下操作:

const void * const real_address

但是,您将无法按照需要在函数中初始化它。我想您可以抛弃函数中的常量,但这在C语言中甚至可能不合法。

只需定义一个。它不能被意外地改变

#define real_address  ( (void*)( (uint32_t)virtual_address | UNCACHE_MASK ) )
每次使用一两条额外指令并不十分昂贵

还要向
virtual\u address
变量添加一个const关键字,这样它就无法更改

const void* const virtual_address = ...

如果定义函数中的
real\u address
,则无法在函数中为其赋值
void const*const
@user694733:谢谢,我修正了我的答案以反映这一点。我最终选择放弃
const
,只需将其声明为全局并在函数中设置地址。在这里,这可能无关紧要,您知道您的arch是32位的,但通常应该使用
uintpttr\u t
来强制转换指向整数的指针。(因为有一天你把你的东西移植到64位,你会后悔的:)好的,谢谢你的提示!我不认为“缓存”在这里意味着你认为它的功能。听起来好像你在谈论虚拟地址,这不是一个缓存概念。缓存不会更改地址。您可能对以下问题的答案感兴趣:您收到的第二个警告,因为您可能将虚拟_地址作为全局地址,并尝试使用非常量表达式初始化它。因此,您的代码中有两个不同的问题。很好的提示,它实际上解决了我的代码摘录中的问题,但是我正在寻找优化,
real\u address
用于其他计算,我希望避免这些额外的指令。如果这种重新计算真的是一个瓶颈(我对此表示怀疑)您可以尝试在变量的开头存储该值一次。如果您经常使用该变量,它在缓存中应该始终是热的,并且在重新加载时不会产生太多开销。
const void* const virtual_address = ...