我很难理解这一点,它将字符串写入结构的字段:
struct_t* P = (struсt_t*)malloc(sizeof(struct_t))
size_t offset = offsetof(struct, field);
char **strfield = (char **)(((char *)P) + offset);//the bit I don't fully understand
gets (string);
*strfield = malloc (strlen (string) + 1);
strcpy (*strfield, string);
如何正确缠绕?我的意思是括号和星号。
P.S。这是程序的一部分,其中offset值定义函数的行为,具体取决于调用它的偏移值的参数。也就是说,它要么填写P->性别,要么填充P->。
答案 0 :(得分:2)
编辑:写完这个答案后,问题已经有所澄清,可能会使答案不太合适。但是,我保留其余内容不变,因为仍然不清楚OP的实际代码是什么样的。
看起来编写此代码的人需要在结构的同一字段中存储不同的类型。为什么你只是为了访问结构成员而跳过这样的箍?看到struct_t
的定义会很有启发性,但让我们说它看起来像这样:
struct struct_t {
T1 f1;
T2 f2;
int field;
};
为了在不同时间将field
成员用于不同类型的数据,您需要通过适当类型的指针访问它。
首先我们需要field
成员的地址:
size_t offset = offsetof(struct, field);
offsetof
运算符从结构的第一个字节为您提供结构成员的偏移量。然后,您需要计算指向此地址的指针,并将其强制转换为适当的类型。
首先是指向结构的第一个字节的指针,然后将其强制转换为字符类型:
char **strfield = (char **)(((char *)P) + offset);
然后添加偏移量:
char **strfield = (char **)(((char *)P) + offset);
如果要在char *
中存储指向char(field
)的指针,则指向 field
的指针必须是指针指向char(char **
)的指针:
char **strfield = (char **)(((char *)P) + offset);
现在我们要在field
中存储内容,但使用strfield
来存储我们想要的实际数据类型:
*strfield = malloc (strlen (string) + 1);
strcpy (*strfield, string);
*strfield
取消引用指向field
的指针,从malloc()
返回的指针存储在结构内field
成员的位置,并将字符串复制到分配的内存。
这很糟糕,因为field
成员未必为您要存储的类型正确对齐。这会导致未定义的行为,这可能导致程序崩溃,运行缓慢,提供不正确的结果或完全意外的事情。或者最糟糕的是,多年来一直运行良好直到为大客户做示范。
幸运的是,C有办法正确地做到这一点:
正确且更简单的方法是使用union
:
struct struct_t {
T1 f1;
T2 f2;
union {
int intfield;
char *strfield;
int (*functionfield)(char *, ...);
} field;
};
现在,您可以field
成员P->field.strfield
或任何其他类型访问{{1}}成员,并保证该字段已正确对齐联盟内的所有类型。
当然,只有在通过同一个union成员存储和检索值时,或者至少通过相同类型的指针,才会定义行为。
答案 1 :(得分:1)
您希望strfield
指向field
中的P
。 field
是结构中的char *
成员,因此其指针strfield
是char **
变量。
field
位于P
起始地址+ offset
字节。
由于指针算术,如果你想要添加offset
字节,你必须将P转换为char *
,否则你将offset
的大小增加struct_t
倍结构。
答案 2 :(得分:1)
char **strfield = (char **)(((char *)P) + offset);//the bit I don't fully understand
是在结构中一般访问字段的另一种方法。 strfield
,可推测的sting-field是指向指针的指针,该指针将用于保存指向结构中字符串字段的指针的地址。如果您有结构,则可以使用正常.
或->
运算符或访问其成员,并使用结构+ offset
的名称。
上面的代码是创建一个指向地址P + offset
的指针的指针,以便访问该地址的结构成员。例如,如果你有一个结构:
struct mystruct {
int myint;
char *mystr;
} mystruct;
您希望访问mystruct.mystr
,您可以创建指向mystruct + offset
的指针,其中偏移量等于sizeof (int)
。因此,您将创建一个包含地址mystruct + sizeof (int)
的指针(或指向指针的指针),以便访问该地址的mystr
。这种访问方式通常用于利用空数据类型等的通用数据结构(链表等)。希望这会有所帮助。
另一个工具,offsetof
命令可以帮助进行偏移计算。有关更深入的解释和良好示例,请参阅man offsetof