如果只使用第一个元素,我是否必须为整个结构分配mem?

时间:2015-02-09 15:59:47

标签: c struct

我有一个结构,其中第一个元素被测试并且依赖于它的值,结构的其余部分将被读取或不被读取。在第一个元素的值指示不读取结构的其余部分的情况下,我是否必须为整个结构或仅第一个元素分配足够的内存?

struct element
{
    int x;
    int y;
};

int foo(struct element* e)
{
    if(e->x > 3)
        return e->y;
    return e->x;
}

在main中:

int i = 0;
int z = foo((struct element*)&i);

我假设如果仅为第一个元素分配有效,那么我将不得不警惕任何可能试图复制结构的东西。即将结构传递给函数。

3 个答案:

答案 0 :(得分:1)

请勿将您的信息强制转换为不需要的结构:不要使用结构作为函数的参数。

将结构的成员传递给函数或使用继承:

typedef struct {
    int foo;
} BaseA;

typedef struct {
    int bar;
} BaseB;

typedef struct {
    BaseA a;
    BaseB b;
} Derived;

void foo(BaseB* info) { ... }

...
Derived d;
foo(&d.b);
BaseB b;
foo(&b);

如果你只是好奇(并且认真地不使用它):你可以。

typedef struct {
    int foo, goo, hoo, joo;
} A;

typedef struct {
    int unused, goo;
} B;

int foo(A* a) { return a->goo; }

...
B b;
int goo = foo((A*)&b);

通常,您必须分配一块内存,其数量至少与完全读取结构中具有最大偏移量的被访问成员所需的字节数相同。此外,在写入此块时,您必须确保使用与原始结构中相同的成员偏移量。

关键是,一个结构只是一个内存块,不同的区域分配了不同的解释(int,char,其他结构等......)和访问结构的一个成员(在重新排序和对齐之后)归结为简单读取或写入一点记忆。

答案 1 :(得分:1)

我不认为给出的代码是合法的。要了解原因,请考虑:

struct CHAR_AND_INT { unsigned char c; int i; }
CHAR_AND_INT *p;

编译器有权假设p->c将是字对齐的,并且p->i也需要填充以进行字对齐。在某些处理器上,写一个字节可能比写一个字慢。例如,字节存储指令可能要求处理器从存储器中读取字,更新其中的一个字节,然后将整个字写回,而字存储指令可以简单地存储新数据而无需先读取任何内容。 。知道p->c将进行字对齐和填充的编译器可以通过使用字存储来写入值12来实现p->c = 12;。这样的行为不会产生期望的结果,但是,如果字节跟随p->c没有填充,而是保留了有用的数据。

虽然我不希望编译器对原始问题中显示的结构的任何部分施加“特殊”对齐或填充要求(超出适用于int的那些部分)但我不认为标准会禁止编译器这样做。

答案 2 :(得分:0)

您只需检查结构本身是否已分配;不是成员(至少在这种情况下)

int foo(struct element* e)
{
   if ( e != 0) // check that the e pointer is valid
   {
      if(e->x != 0) // here you only check to see if x is different than zero (values, not pointers)
        return e->y;
   }
    return 0;
}

在您编辑的更改中,我认为这是一个糟糕的编码

int i = 0; int z = foo((struct element *)& i);

在这种情况下,我将在堆栈上进行分配,因此其地址有效;并且将在foo中有效;但既然你把它变成了不同的东西,成员就会变成垃圾(充其量) 为什么要将int转换为结构? 你的意图是什么?