2012-04-23 92 views
1

我想创建一个函数,获取一个空指针。这个指针指向一个任意的用户数据。这与现在无关。描述这个用户数据的描述符更重要。在这个数据下是。我想它的地址,有两种不同的解决方案:奇怪的行为与空指针

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 */ 
} 

正如你可以看到我用两个不同势的方法获得描述符的地址。我认为第一个更自然,但这不起作用。我用更多的括号来避免优先问题。

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

在此先感谢!

+0

能否请您明确一些事情? ptr指向什么?类型或大小,还是什么? – 2012-04-23 01:44:17

+0

这将是一个内存分配器,ptr传递给用户,所以它可以是任何用户数据。为了组织这些块,描述符存储一些关于这个的信息,大小和前一个和第二个块的指针。当free()来的时候,它只会得到ptr,所以它必须以某种方式获得信息。最简单的方法是将其附加到用户数据。 – 2012-04-23 01:50:33

回答

2

问题是指针算术。当你拿一个指针并减去1时,你真的减去了(1*sizeof(struct))。带“-sizeof”的第一个等式,你真的从指针中减去了(sizeof(struct) * sizeof(struct))个字节。合理?

1

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

+0

你说得对。第一种情况也是这样做的。从ptr中减去就像将desc减1。我认为问题在于字体大小。恕我直言,它应该与一个字符指针工作,因为它只有一个字节宽,sizeof(struct desc_data)也是以字节为单位。 – 2012-04-23 01:56:58

+1

我不完全确定你的意思。如果你说你可以定义'char * desc'然后使用你的原始计算,那么你是对的......但是你不能解析desc,因为它指向一个'char',而不是' data_desc'结构。 – 2012-04-23 01:58:36

1
desc = ((struct data_desc *)ptr) - sizeof(struct data_desc); 

你强制转换ptrstruct data_desc *。现在,编译器在这个指针上执行的所有算法都是指向它指向的类型的大小。

所以,如果你减去sizeof(struct data_desc)(假设struct data_desc的大小8个字节),ptr将指向可以容纳8 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