使用负偏移量的变量分配记录

时间:2017-06-08 14:58:47

标签: c

当为记录指针分配内存时,我还需要一个位于分配记录之前的整数指针的空间。此指针不能是记录本身的一部分,也不能放在记录之后。我目前的做法如下:

#include <stdlib.h>

static int n;
struct { int f; } *p;

p = malloc(sizeof (int *) + sizeof *p);
if (p != NULL) {
    p = (void *) ((int **) p + 1);
    *((int **) p - 1) = &n;
}

演员表是否定义明确?如果没有,我该怎么做呢?

编辑:

我想要实现的是实现可扩展记录(OOP),整数指针表示类型ID。扩展记录应与其基本类型兼容。但是,我只需要类型ID:s作为指向记录的指针。这是一个完整的例子:

#include <assert.h>
#include <stdlib.h>

struct T0 {
    int f;
};
int T0ID;

struct T1 {
    struct T0 base;
    int g;
};
int T1ID;

int main(void)
{
    struct T0 *x;
    struct T1 *y;

    y = malloc(sizeof (int *) + sizeof *y);
    if (y != NULL) {
        *((int **) y) = &T1ID;
        y = (void *) ((int **) y + 1);
        ((struct T0 *) y)->f = 1;
        y->g = 2;
    }
    x = (struct T0 *) y;
    assert(x->f == 1);
    return 0;
}

2 个答案:

答案 0 :(得分:2)

我不确定你的做法是好的。特别是我担心改变p的价值。当你需要释放内存时,你将需要该值。

我会将int*和结构包装在另一个结构中。类似的东西:

static int n;
struct someData { int f; };

struct wrapper {int* pn; struct someData data;};

struct someData* pd; // Pointer to the data struct


struct wrapper* pw = malloc(sizeof *pw);

if (pw != NULL) {
    pw->pn = &n;
    pd = &pw->data;
}

答案 1 :(得分:1)

将代码(任意)转换为特定对象类型的代码可能由于不正确的对齐而产生未定义的行为(参见 C standard draft):

  

6.3.2.3指针

     

(7)指向对象类型的指针可以转换为指向a的指针   不同的对象类型。如果结果指针不正确   对于引用的类型,行为是未定义的。

您有一个声明为struct{int}*类型的指针指向(更大的内存块),然后转换指针并对(已转换的)指针执行算术运算。由于无法保证int *struct{int}*以相同的方式对齐,因此无法保证行为已定义。

为避免这种情况,请将您的结构和前一个整数封装在另一个结构中,例如:如下:

static int n;

struct data_struct {
    int f;
};

struct enclosing_struct {
    int *nPtr;
    struct data_struct data;
};


int main() {

    struct enclosing_struct *e = malloc (sizeof(struct enclosing_struct));
    e->nPtr = &n;
    struct data_struct *dataPtr = &e->data;

    return 0;
}