If only using the first element, do I have to allocate mem for the whole struct?

核能气质少年 提交于 2019-12-23 19:57:14

问题


I have a structure where the first element is tested and dependent on its value the rest of the structure will or will not be read. In the cases where the first element's value dictates that the rest of the structure will not be read, do I have to allocate enough memory for the entire structure or just the first element?

struct element
{
    int x;
    int y;
};

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

in main:

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

I assume that if only allocating for the first element is valid, then I will have to be wary of anything that may attempt to copy the structure. i.e. passing the struct to a function.


回答1:


don't force your information into structs where it's not needed: don't use the struct as the parameter of your function.

either pass the member of your struct to the function or use inheritance:

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);

if you're just curious (and seriously don't use this): you may.

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);

In general you'll have to allocate a block of memory at least as many bytes as are required to fully read the accessed member with the largest offset in your structure. In addition when writing to this block you have to make sure to use the same member offsets as in the original structure.

The point being, a structure is only a block of memory with different areas assigned different interpretations (int, char, other structs etc...) and accessing a member of a struct (after reordering and alignment) boils down to simply reading from or writing to a bit of memory.




回答2:


I do not think the code as given is legitimate. To understand why, consider:

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

A compiler would be entitled to assume that p->c will be word-aligned and have whatever padding would be necessary for p->i to also be word-aligned. On some processors, writing a byte may be slower than writing a word. For example, a byte-store instruction may require the processor to read a word from memory, update one byte within it, and write the whole thing back, while a word-store instruction could simply store the new data without having to read anything first. A compiler that knew that p->c would be word-aligned and padded could implement p->c = 12; by using a word store to write the value 12. Such behavior wouldn't yield desired results, however, if the byte following p->c wasn't padding but instead held useful data.

While I would not expect a compiler to impose "special" alignment or padding requirements on any part of the structure shown in the original question (beyond those which apply to int) I don't think anything in the standard would forbid a compiler from doing so.




回答3:


You need to only check that the structure itself is allocated; not the members (in that case at least)

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;
}

In you edited change, I think this is poor coding

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

In that case, i will be allocation on the stack, so its address is valid; and will be valid in foo; but since you cast it into something different, the members will be garbage (at best) Why do you want to cast an int into a structure? What is your intent?



来源:https://stackoverflow.com/questions/28413882/if-only-using-the-first-element-do-i-have-to-allocate-mem-for-the-whole-struct

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!