1

我想创建一个获取 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 */
}

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

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

提前致谢!

4

3 回答 3

2

问题是指针算术。当你拿一个指针减去 1 时,你实际上是在减去(1*sizeof(struct))。第一个带有“-sizeof”的等式,实际上是(sizeof(struct) * sizeof(struct))从指针中减去字节。说得通?

于 2012-04-23T01:52:50.743 回答
1

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

编写这样的代码很常见:

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然后直接使用它。

于 2012-04-23T01:48:32.897 回答
1
desc = ((struct data_desc *)ptr) - sizeof(struct data_desc);

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

因此,如果您减去sizeof(struct data_desc)(假设struct data_desc大小为 8 个字节),ptr将指向一个可以struct data_desc在其自身和ptr.

假设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           
于 2012-04-23T01:56:52.200 回答