假设我有一个结构如:
typedef struct
{
char * string1;
char * string2;
} TWO_WORDS;
这样所有字段都是相同的类型,而我的主要字段是
TWO_WORDS tw;
我可以用tw [0]引用string1,用两个[1]引用string2吗?如果是这样的话:
答案 0 :(得分:6)
正如@ouah所指出的,不,你不能那么做。但是,您可以:
typedef union
{ char *a[2];
struct
{ char *string1;
char *string2;
} s;
} TWO_WORDS;
TWO_WORDS t;
t.a[0] = ...;
t.a[1] = ...;
t.s.string1 = ...;
t.s.string2 = ...;
答案 1 :(得分:5)
我对这个结构非常接近:
((char**)&tw)[0];
举个例子:
int main()
{
typedef struct
{
char * string1;
char * string2;
} TWO_WORDS;
TWO_WORDS tw = {"Hello", "World"};
printf("String1: %s\n", ((char**)&tw)[0]);
printf("String2: %s\n", ((char**)&tw)[1]);
return 0;
}
无法保证工作,因为编译器可能会在字段之间添加填充。 (许多编译器都有一个#pragma
,可以避免填充结构)
回答您的每个问题:
是c标准的一部分吗? 否强>
我必须先将结构转换为数组吗?的是
内存大小不同的字段如何这可以用更“邪恶”的演员和指针数学来完成
那些不同类型但大小相同的字段呢?这可以通过更“邪恶”的演员和指针数学来完成
你能在一个结构中做指针运算吗?
是 (不能保证总是像你想象的那样工作,但结构只是一块记忆您可以使用指针和指针 - 数学访问
答案 2 :(得分:3)
不,您不能对结构数据成员使用索引访问,除非您采取特定步骤来模拟它。
在C ++中,可以使用特定于C ++的指针类型(称为“指向数据成员的指针”)来模拟此功能。 C语言没有这种类型,但它可以通过使用标准的offsetof
宏和指针算法来模拟。
在您的示例中,它可能如下所示。首先,我们准备一个特殊的偏移数组
const size_t TW_OFFSETS[] =
{ offsetof(TWO_WORDS, string1), offsetof(TWO_WORDS, string2) };
此偏移数组稍后用于组织对struct成员的索引访问
*(char **)((char *) &tw + TW_OFFSETS[i]);
/* Provides lvalue access to either `tw.string1` or `tw.string2` depending on
the value of `i` */
它看起来不漂亮(尽管可以通过使用宏来使其看起来更好),但这就是它在C中的方式。
例如,我们可以定义
#define TW_MEMBER(T, t, i) *(T *)((char *) &(t) + TW_OFFSETS[i])
并在代码中使用它
TW_MEMBER(char *, tw, 0) = "Hello";
TW_MEMBER(char *, tw, 1) = "World";
for (int i = 0; i < 2; ++i)
printf("%s\n", TW_MEMBER(char *, tw, i));
请注意,基于将结构重新解释为char*[2]
数组(无论是通过联合还是通过强制转换完成),此方法不存在解决方案中存在的严重问题。后者是一种黑客,从正式的角度来看是非法的,通常是无效的。基于offsetof
的解决方案完全有效且合法。
答案 3 :(得分:2)
我可以用tw [0]引用string1,用两个[1]引用string2吗?
不,你不能在C中,tw
是一个结构而不是指针。
[]
运算符的约束要求其中一个操作数是指针类型。
要访问string1
,您可以使用以下表达式:tw.string1
答案 4 :(得分:1)
不,你不能在C中这样做。你只能通过他们的名字访问C中的struct成员。
你可以做的是构建一个数组,该数组具有与结构中相同字符串的指针,然后使用数组的索引。
但你为什么要那样做呢?你实际上试图解决的问题是什么?
答案 5 :(得分:1)
如果您真的想要,可以使用((char **)&tw)[0]
来执行此操作,但不能使用tw[0]
。
答案 6 :(得分:0)
如果其中一个struct
以相同类型的字段开头,则可以声明union
,其中包含该类型的结构以及相应字段类型的数组。如果这样做,读取或写入数组的元素将读取或写入适当的结构成员。这种行为适用于我所知道的所有实现,如果所有字段大小相同,我相信它是可移植的。
struct quad_int {int n0; int n1; int n2; int n3;} union quad_int_union {struct pair p; int n[4];} union quad_int_union my_thing; my_thing.n[0] is synonymous with my_thing.p.n0 my_thing.n[1] is synonymous with my_thing.p.n1 etc.