【问题标题】:Strange behaviour with void pointers空指针的奇怪行为
【发布时间】:2012-04-23 01:41:10
【问题描述】:

我想创建一个获取 void 指针的函数。该指针指向任意用户数据。这与现在无关。哪个描述符更重要,它描述了这个用户数据。 在此数据下。我想得到它的地址,有两种不同的解决方案:

struct data_desc {
     size_t size;
     data_type_t type;
     /* And so on... */
};

/* Operate on the descriptor */
void operate_on_data(void *ptr)
{
    struct data_desc *desc;
    /* Now I want to get the desc /*

    /* This is the first approach, simply fails */
    desc = ((struct data_desc *)ptr) - sizeof(struct data_desc);
    /* This is the second, it works...*/
    desc = (struct data_desc *)ptr;
    desc--; 
    /* Do something with desc */
}

如您所见,我使用两种不同的方法获取描述符的地址。我认为第一个更自然,但它只是行不通。我使用了更多的括号来避免优先级问题。

我知道这些方法不安全第一个不起作用,为什么?这种行为背后的原因是什么?

提前致谢!

【问题讨论】:

  • 你能澄清一些事情吗? ptr 指向什么?输入或大小,还是什么?
  • 这将是一个内存分配器,将ptr传递给用户,所以它可以是任何用户数据。为了组织这些块,描述符存储一些关于这个、大小以及前一个和第二个块的指针的信息。当 free() 来的时候,它只获取 ptr,所以它必须以某种方式获取信息。最简单的方法是将其附加到用户数据。

标签: c pointers void


【解决方案1】:

问题是指针算法。当您使用指针并减去 1 时,您实际上是在减去 (1*sizeof(struct))。第一个带有“-sizeof”的等式,实际上是从指针中减去(sizeof(struct) * sizeof(struct)) 字节。有意义吗?

【讨论】:

    【解决方案2】:

    当您将data_desc 定义为指向struct data_desc 的指针时,当您将指针递增或递减1 时,编译器就会知道要加或减sizeof(struct data_desc)。换句话说,它将“一个”翻译成“一个结构”。

    这样写代码很常见:

    struct data_desc *desc = (struct data_desc *) ptr;
    

    然后你可以像这样操作它:

    size_t sz0 = desc->size;  // size of 0th element
    size_t sz1 = desc[1].size;  // size of 1st element
    size_t sz2 = (desc + 2)->size; // size of 2nd element (slightly awkward)
    desc++;  // Increment to next structure
    

    回到你原来的代码:你可以desc = ((struct data_desc *)ptr) - 1;,但大多数程序员更喜欢初始化desc,然后直接使用它。

    【讨论】:

    • 你是对的。第一种情况也是这样做的。从 ptr 中减去就像将 desc 减一一样。我认为问题在于字体大小。恕我直言,它应该使用 char 指针,因为它只有一个字节宽,sizeof(struct desc_data) 也以字节为单位。
    • 我不太清楚你的意思。如果您说您可以定义char *desc,然后使用您的原始计算,那么您是对的……但是您不能取消引用desc,因为它指向char,而不是data_desc结构。
    【解决方案3】:
    desc = ((struct data_desc *)ptr) - sizeof(struct data_desc);
    

    您已将ptr 类型转换为struct data_desc *。现在,编译器对该指针执行的所有算术运算都以它指向的类型的大小为单位。

    因此,如果您减去 sizeof(struct data_desc)(假设 struct data_desc 的大小为 8 个字节),ptr 将指向一个可以在其自身和 ptr 之间容纳 8 个 struct data_desc 的位置。

    假设下面每个loc可以容纳一个struct data_desc

    -------------------------------------------------------------
    |     |     |     |     |     |     |     |     |     |     |
    | loc | loc | loc | loc | loc | loc | loc | loc | loc | ptr | 
    |  9  |  8  |  7  |  6  |  5  |  4  |  3  |  2  |  1  |     |
    -------------------------------------------------------------
          ^                                               ^
          |                                               |
         desc                                            ptr 
         location                                        location
         after
         subtraction           
    

    【讨论】:

      猜你喜欢
      • 2020-01-22
      • 1970-01-01
      • 1970-01-01
      • 2020-11-28
      • 2021-07-01
      • 2013-03-31
      • 2019-04-27
      • 2012-05-29
      • 1970-01-01
      相关资源
      最近更新 更多