如果只使用第一个元素,我是否必须为整个结构分配内存?
If only using the first element, do I have to allocate mem for the whole struct?
我有一个结构,其中测试了第一个元素,并根据它的值读取或不读取结构的其余部分。在第一个元素的值决定不读取结构的其余部分的情况下,我是否必须为整个结构或仅为第一个元素分配足够的内存?
struct element
{
int x;
int y;
};
int foo(struct element* e)
{
if(e->x > 3)
return e->y;
return e->x;
}
主要内容:
int i = 0;
int z = foo((struct element*)&i);
我假设如果只为第一个元素分配是有效的,那么我将不得不警惕任何可能试图复制结构的东西。即将结构传递给函数。
您只需要检查结构本身是否已分配;不是成员(至少在那种情况下)
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);
那样的话,i会分配到栈上,所以它的地址是有效的;并且在 foo 中有效;但是因为你把它变成了不同的东西,成员将是垃圾(充其量)
为什么要将 int 转换为结构?
你的意图是什么?
不要将您的信息强加到不需要的结构中:不要将结构用作函数的参数。
要么将结构的成员传递给函数,要么使用继承:
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、其他结构等...)并且访问结构的成员(在重新排序和对齐之后)归结为简单地读取或写入一些内存。
我认为给出的代码不合法。要了解原因,请考虑:
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
不是填充而是保存有用的数据。
虽然我不希望编译器对原始问题中显示的结构的任何部分施加 "special" 对齐或填充要求(除了那些适用于 int
的部分)我不认为标准中的任何内容都会禁止编译器这样做。
我有一个结构,其中测试了第一个元素,并根据它的值读取或不读取结构的其余部分。在第一个元素的值决定不读取结构的其余部分的情况下,我是否必须为整个结构或仅为第一个元素分配足够的内存?
struct element
{
int x;
int y;
};
int foo(struct element* e)
{
if(e->x > 3)
return e->y;
return e->x;
}
主要内容:
int i = 0;
int z = foo((struct element*)&i);
我假设如果只为第一个元素分配是有效的,那么我将不得不警惕任何可能试图复制结构的东西。即将结构传递给函数。
您只需要检查结构本身是否已分配;不是成员(至少在那种情况下)
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);
那样的话,i会分配到栈上,所以它的地址是有效的;并且在 foo 中有效;但是因为你把它变成了不同的东西,成员将是垃圾(充其量) 为什么要将 int 转换为结构? 你的意图是什么?
不要将您的信息强加到不需要的结构中:不要将结构用作函数的参数。
要么将结构的成员传递给函数,要么使用继承:
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、其他结构等...)并且访问结构的成员(在重新排序和对齐之后)归结为简单地读取或写入一些内存。
我认为给出的代码不合法。要了解原因,请考虑:
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
不是填充而是保存有用的数据。
虽然我不希望编译器对原始问题中显示的结构的任何部分施加 "special" 对齐或填充要求(除了那些适用于 int
的部分)我不认为标准中的任何内容都会禁止编译器这样做。