【问题标题】:Casting in C to access specific bytes in a variable在 C 中进行强制转换以访问变量中的特定字节
【发布时间】:2020-08-16 15:38:11
【问题描述】:

我有一个 8 字节长的 void * 变量,就像所有指针一样。我正在使用 8 字节格式的地址,因为它们存储在指针中,但足够小,只能用 4 个字节表示。我想让void * 变量的前 4 个字节为一个地址,而后 4 个字节为另一个地址;

所以如果我有void *p = 0x0000000000000000 并且我有其他指针 void *a = 0x12345678void *b = 0x12345678 我想以void *p = 0x1234567812345678 结束

我正在尝试使用以下功能:

void set_ptr(void *p, void *first_ptr, void *second_ptr){
   *(unsigned int *)(p) = (unsigned int)(first_ptr);
   *(unsigned int *)((char*)p + 4) = (unsigned int)(second_ptr);
}

这会起作用还是有更好的方法来做到这一点?

【问题讨论】:

  • p = (void*)(((uint64_t)a << 32) | (uint32_t)b)。但这是非常脆弱的,并且可能具有未定义的行为。
  • 而不是void* 使用uint64_t: ... uint64_t final = ((uint64_t)((uint32_t)0x12345678) << 32) + (uint32_t)0x12345678; /* thanks @EricPostpischil*/ 记得#include

标签: c pointers casting


【解决方案1】:

使用memcpy。比如:

void f(void *p, const void *a, const void *b) {
    memcpy(&p, &a, 4);
    memcpy(((char *)p) + 4, &b, 4);
}

【讨论】:

    【解决方案2】:

    首先,要知道这将是非常脆弱和不可移植的。显然,如果为具有 32 位指针的处理器编译,它将无法工作。但是,如果您只是想要在您的机器上运行的东西,我建议您定义一个新类型,如下所示:

    typedef struct {
        uint32_t p1;
        uint32_t p2;
    } DoublePointer;
    

    然后您可以轻松地访问这两个指针作为DoublePointer 结构中的字段。如果您需要将结构分配给单个指针,那也很容易:

    DoublePointer doublePointer;
    doublePointer.p1 = 0x12345678;
    doublePointer.p2 = 0x12345678;
    void *frankenpointer = (void*) *((uint64_t*) &dp);
    

    我有没有提到这很脆弱?我不建议走这条路,否则有人会继承这段代码并希望他们有一份不同的工作。

    【讨论】:

    • void *frankenpointer = (void *) doublepointer;???这超出了脆弱性——它将struct Doublepointer 转换为void *。顺便说一句,这是一个语法错误。
    • 谢谢安德鲁,你完全正确。您必须首先转换为标量。我已经修复了它,所以它可以编译。 (我仍然认为这是一个坏主意,但我假设这样做有一些我没有想到的正当理由。)
    猜你喜欢
    • 1970-01-01
    • 2016-11-10
    • 1970-01-01
    • 2011-08-31
    • 1970-01-01
    • 2015-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多