我们可以为给定的内存位置分配值吗?

时间:2012-02-21 06:02:20

标签: c memory pointers

我想将一些值(比如2345)分配给一个内存位置(比如0X12AED567)。可以这样做吗?

换句话说,我该如何实现以下功能?

void AssignValToPointer(uint32_t pointer, int value)
{

}

7 个答案:

答案 0 :(得分:15)

你问这个问题的事实表明你已经过了头脑。但是你走了:

*(int *)0x12AED567 = 2345;

答案 1 :(得分:3)

答案取决于一些因素。您的程序是否在现代操作系统中运行?

如果是,尝试访问未映射的内存区域将导致SIGSEGV。要实现这一点,您必须使用特定于系统的函数来映射包含此确切地址的内存区域,然后再尝试访问它。

答案 2 :(得分:2)

将内存位置视为指针

int* pMemory =  OX12AED567;
*pMemory = 2345;

注意:只有当您的程序可以访问和写入该内存位置时,这才有效。写入这样的任意内存位置本质上是危险的。

答案 3 :(得分:2)

就C而言,这是未定义的行为。我的以下建议也是未定义的行为,但避免了所有基于类型和基于别名的问题:使用字符。

int a = get_value();
char const * const p = (const char * const)&a;
char * q = (char *)0x12345;

memcpy(q, p, sizeof(int));

或者,您可以直接访问字节q[i]。 (这是UB的部分:指针q不是作为实际对象的地址获得的,也不是作为分配函数的结果获得的。有时这是正常的;例如,如果你正在写一个免费的在实模式下运行并访问图形硬件的程序,您可以直接在一个众所周知的硬编码地址写入图形存储器。)

答案 4 :(得分:1)

您已经指出,该地址是一个物理地址,并且您的代码正在一个过程中运行。

所以,如果你是

  1. 在某种高级操作系统中,例如Linux,你必须得到一个映射到物理地址空间。在Linux中,/ dev / mem会为您做到这一点。

  2. 在内核中或没有操作系统且使用MMU时,您必须将物理地址转换为虚拟地址。在Linux内核中,phys_to_virt()为您做到了这一点。在内核中,我假设,这个地址总是被映射。

  3. 在内核中或没有操作系统且没有MMU的情况下,直接写入该地址。根本没有可以考虑的映射。

  4. 现在,您有一个有效的映射或物理地址本身,您传递给您的函数。

    void AssignValToPointer(uint32_t pointer, int value)
    {
        * ((volatile int *) pointer) = value;
    }
    

    您可能希望添加volatile关键字,因为如果您之后没有从该位置读取(可能是写入内存映射硬件的寄存器的情况),编译器可能会优化写操作。

    您可能还想使用uintptr_t数据类型而不是uint32_t作为指针。

答案 5 :(得分:1)

C99标准草案

如果没有实现定义的行为,这可能是不可能的。

关于演员表:

*(uint32_t *)0x12AED567 = 2345;

C99 N1256 standard draft" 6.3.2.3指针"表示:

  

5整数可以转换为任何指针类型。除非事先指明,否则   结果是实现定义的,可能没有正确对齐,可能不指向   引用类型的实体,可能是陷阱表示。 56)

GCC实施

GCC将其int指向以下的指针实现:https://gcc.gnu.org/onlinedocs/gcc-5.4.0/gcc/Arrays-and-pointers-implementation.html#Arrays-and-pointers-implementation

  

如果指针表示小于整数类型,则从整数到指针的强制转换丢弃最高有效位,如果指针表示大于整数类型,则根据整数类型的符号扩展,否则位不变。

所以演员阵容将按预期为此实施工作。我希望其他编译器能做类似的事情。

答案 6 :(得分:0)

条件是它不便携或安全(根本):

*((int *)0x12AED567) = 2345;