使用uint64_t作为内存的通用地址而不是void *的利弊是什么?

时间:2017-07-24 05:38:54

标签: c++ c

我是C编程的新手。我发现{libnerver中uint64_t用作缓冲区的地址而不是void*

struct ibv_sge{
    uint64_t addr;
    uint32_t length;
    uint32_t lkey;
}

我能想到的一个缺点是它的便携性。在32位系统上,它将导致编译错误或至少浪费内存。那为什么呢?有什么好处吗?

我还注意到还有其他替代方法,例如uintptr_t。什么是描述通用内存地址的最佳方法?

2 个答案:

答案 0 :(得分:0)

  

使用uint64_t作为内存的通用地址的优缺点

缺点:

  1. 当较窄的通用地址时,它可能会不必要地广泛。

  2. 当需要更广泛的通用地址时,它可能会不必要地缩小。

  3. C没有通用地址。最接近的是void *,但只指定对象指针就足够了。 void *可能不足以用于函数指针。任何函数指针类型与另一个函数指针类型的大小相同。

      

    指向void的指针可以转换为指向任何对象类型的指针。指向任何对象类型的指针可以转换为指向void并再次返回的指针;结果应该等于原始指针。 C11dr§6.3.2.31

         

    指向一种类型的函数的指针可以转换为指向另一种类型的函数的指针,然后再返回;结果应该等于原始指针。 §6.3.2.38

      

    描述通用内存地址的最佳方法是什么?

    使用C代替union

    union u_pointer {
      void *obj;
      int (*fun)();
    };
    

    访问读写这些成员需要仔细处理,就像任何通用指针一样。

答案 1 :(得分:0)

在C ++中,永远不需要int,也不需要void*作为指针类型。

该库似乎是大约13 000行C.从the current master复制的结构使用示例:

static int pp_post_recv(struct pingpong_context *ctx, int n)
{
        struct ibv_sge list = {
                .addr   = (uintptr_t) ctx->buf,
                .length = ctx->size,
                .lkey   = ctx->mr->lkey
        };
        struct ibv_recv_wr wr = {
                .wr_id      = PINGPONG_RECV_WRID,
                .sg_list    = &list,
                .num_sge    = 1,
        };
        struct ibv_recv_wr *bad_wr;
        int i;

        for (i = 0; i < n; ++i)
                if (ibv_post_srq_recv(ctx->srq, &wr, &bad_wr))
                        break;

        return i;
}

对我而言,.addr似乎是缓冲区中的偏移量。因此,指针类型会被误导。