【问题标题】:Get memory address获取内存地址
【发布时间】:2015-08-04 21:10:07
【问题描述】:

我们如何通过这样的调用函数返回内存区域的地址:

// memory_region malloc'ed before this
uint64 address = get_memory_region_address (memory_region);
printf(">> memory_region (address) = 0x%lX\n",  address);   
printf(">> memory_region (address) = %p\n",  address);  

uint64 get_memory_region_address (int* memory_region) {
    uint64* address_of_memory = 0;

    address_of_memory_region = (uint64) memory_region;

    return address_of_memory;  
}

【问题讨论】:

  • “内存区域地址”是什么意思?如果 memory_region 被 malloc 了,那么它 是 该区域的地址。你的函数get_memory_region_address() 没有多大意义。
  • 你到底想用这个完成什么?
  • 只是为了获取地址。它用于特定用途。你能告诉我如何返回地址吗?
  • 你今天已经问过这个问题并得到了一些答案。但我没有看到你雇用了他们。
  • 你能提供一个工作代码吗,@EugeneSh。

标签: c pointers memory call


【解决方案1】:

保证能够存储指针的正确整数类型是intptr_t 或uintptr_t。

7.18.1.4 能够保存对象指针的整数类型

以下类型指定有符号整数类型,其属性是任何指向 void 的有效指针都可以转换为该类型,然后转换回指向 void 的指针,结果将与原始指针进行比较:@ 987654323@

以下类型指定了一个无符号整数类型,其属性是任何指向 void 的有效指针都可以转换为该类型,然后再转换回指向 void 的指针,结果将与原始指针进行比较:@ 987654324@

不幸的是,这些类型是可选的

你的代码应该是:

uintptr_t get_memory_region_address (int* memory_region) {

    address_of_memory_region = (uintptr_t) memory_region;

    return address_of_memory;  
}
uintptr_t address = get_memory_region_address (memory_region);

printf(">> memory_region (address) = %p\n",  (void *) address);  

如果你想控制地址的格式,你可以转换成uintmax_t或者转换成ptrdiff_t

printf(">> memory_region (address) = %0xjX\n",  (uintmax_t) address);  

或

printf(">> memory_region (address) = %0xtX\n",  (ptrdiff_t) address);  

参考资料:

  • ptrdiff_t: 7.17 常用定义<stddef.h>
  • uintmax_t: 7.18.1.5 最大宽度整数类型<stdint.h>
  • 格式化:7.19.6 格式化输入/输出函数,特别是 7.19.6.1 fprintf 函数 §7

【讨论】:

    【解决方案2】:

    这个定义:

    uint64 get_memory_region_address (int* memory_region)
    {
        uint64* address_of_memory = 0;
        // ...
        return address_of_memory;  
    }
    

    没有任何意义。您将 address_of_memory 声明为某个整数类型的 指针,然后将其作为该类型的整数返回。

    基本上有两种方法可以获取对象指针的内存地址。

    格式说明符%p:

    简单地打印为:

    printf(">> memory_region (address) = %p\n",  (void *) memory_region);
    

    需要这种转换为 void 指针以确保最大的可移植性。 printf() 是可变参数函数,其参数(除了fmt)受默认参数提升的约束。这意味着如果在某些实现上:

    sizeof(void *) != sizeof(int *)
    

    保持,然后它会发出一个未定义的行为(严格来说它更早是UB)。

    将指针的值转换为整数类型:

    有一种可移植的方式,使用intptr_t 或uintptr_t。两者都是在<stdint.h> 中定义的可选。这样,你可以得到内存地址:

    uintptr_t get_memory_region_address(int *memory_region)
    {
        return (uintptr_t) memory_region;
    }
    

    然后将其打印为:

    uintptr_t address = get_memory_region_address(memory_region);
    printf(">> memory_region (address) = " PRIXPTR "\n",  address);
    

    甚至更简单:

    printf(">> memory_region (address) = " PRIXPTR "\n", (uintptr_t) memory_region);
    

    【讨论】:

    • 它仍然返回 0。
    • @UrsaMajor:它可能返回0,在这种情况下memory_region是一个空指针。您也可以通过if (memory_region == NULL) { printf(">> memory_region is a null pointer\n"); } 进行检查。请注意,标准库中的某些函数返回 NULL 以指示特殊情况。例如malloc以这种方式表示分配失败。
    • 如果我调用该函数,它只会返回一个 0,如果我这样做,它会起作用:void create_memory_region(int* memory_region, int size_of_memory_region, uint64* address_of_memory_region_designated_start, uint64* address_of_memory_region_designated_end) { memory_region = (int*) malloc (size_of_memory_region * sizeof(int)); *address_of_memory_region_designated_start = (uint64) memory_region; *address_of_memory_region_designated_end = (uint64) (memory_region + size_of_memory_region - 1); printf("address_of_memory_region_designated_start (address) = %p\n", *address_of_memory_region_designated_start);
    • 但是,由于某些原因,我要求在某个调用函数结构中。所以 malloc 确实有效,但是当我将它传递给调用函数结构时,它返回一个 0。
    • @UrsaMajor:我明白了,但你没有在你的问题中这样描述它,应该对其进行编辑以反映这个重要问题(对于未来,不要在这里放长代码 - 没人读它)。无论如何,问题是函数参数memory_region 是指针的本地副本,您已将其传递给函数。这个本地副本可以在函数内部修改,但这与原始指针无关。解决方案是将参数修改为int** memory_region,并将所有后续出现的memory_region 修改为*memory_region,它们都在函数体内。
    【解决方案3】:

    如果memory_region 是一个指向先前分配的内存的指针,它的值应该已经是它的第一个字节的地址。

    试试:

    uint64 address = (uint64) memory_region;
    

    我想我应该提到标准 C 库定义的 NULL = (void*) 0。如果您尝试将这个0x0f 地址作为指针读取/写入,它总是会引发分段错误错误,这就是为什么它被命名为:Null、IfThisPointerVariableHasMeRunAwayFast、WantASegFaultJustReadMe 值

    【讨论】:

    • 嗨,Emisor,它仍然返回零。
    • NULL == (void*) 0 是真的,不是 NULL = (void*) 0。
    • 我的意思是 NULL 在标准 C 的 .h 文件中是这样定义的。为什么我需要进行逻辑比较
    • 如果我调用该函数,它只会返回一个 0,如果我这样做,它会起作用:void create_memory_region(int* memory_region, int size_of_memory_region, uint64* address_of_memory_region_designated_start, uint64* address_of_memory_region_designated_end) { memory_region = (int*) malloc (size_of_memory_region * sizeof(int)); *address_of_memory_region_designated_start = (uint64) memory_region; *address_of_memory_region_designated_end = (uint64) (memory_region + size_of_memory_region - 1); printf("address_of_memory_region_designated_start (address) = %p\n", *address_of_memory_region_designated_start);
    • 但是,由于某些原因,我需要在某个调用函数结构中。
    猜你喜欢
    • 1970-01-01
    • 2015-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-18
    • 2018-09-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多