9

假设我有一个结构,例如:

typedef struct
{
    char * string1;
    char * string2;
} TWO_WORDS;

这样所有的字段都是相同的类型,我的主要有

TWO_WORDS tw;

我可以用 tw[0] 引用 string1,用两个 [1] 引用 string2 吗?如果是这样的话:

  • 这是c标准的一部分吗?
  • 我必须先将结构转换为数组吗?
  • 内存中大小不同的字段呢
  • 不同类型但大小相同的字段呢?
  • 你能在结构中做指针运算吗?
  • -
4

7 回答 7

6

我对这个结构非常接近:

((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标准的一部分吗?

  • 我必须先将结构转换为数组吗?是的

  • 内存中大小不同的字段呢?
    这可以通过更“邪恶”的强制转换和指针数学来完成

  • 不同类型但大小相同的字段呢?
    这可以通过更“邪恶”的铸造和指针数学来完成

  • 你能在结构中做指针运算吗?
    的(不保证总是按您预期的那样工作,但结构只是一块您可以使用指针和指针数学访问的内存)

于 2012-06-05T21:56:20.290 回答
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 = ...;
于 2012-06-05T21:57:11.760 回答
5

不,您不能对结构数据成员使用索引访问,除非您采取特定步骤来模拟它。

在 C++ 中,可以使用称为“指向数据成员的指针”的特定于 C++ 的指针类型来模拟此功能。C 语言没有这种类型,但它可以反过来通过使用标准offsetof宏和指针算法来模拟。

在您的示例中,它可能如下所示。首先,我们准备一个特殊的偏移数组

const size_t TW_OFFSETS[] = 
  { offsetof(TWO_WORDS, string1), offsetof(TWO_WORDS, string2) };

这个偏移数组稍后用于组织对结构成员的索引访问

*(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]数组的解决方案中存在的严重问题(无论它是通过联合还是通过强制转换完成的)。后者是一种 hack,从形式上看是非法的,通常是无效的。基于-offsetof的解决方案是完全有效和合法的。

于 2012-06-05T22:12:50.140 回答
3

我可以用 tw[0] 引用 string1,用两个 [1] 引用 string2 吗?

不,你不能在 C 中,tw是结构而不是指针。

运算符的约束[]要求其中一个操作数是指针类型。

要访问string1,您可以使用以下表达式:tw.string1

于 2012-06-05T21:51:00.433 回答
1

不,您不能在 C 中这样做。您只能通过名称访问 C 中的结构成员。

您可以做的是构建一个数组,该数组具有指向与结构中相同的字符串的指针,然后使用数组的索引。

但是你为什么要这样做呢?您实际上要解决的问题是什么?

于 2012-06-05T21:52:15.167 回答
1

((char **)&tw)[0]如果你真的想这样做,你可以使用它,但不是tw[0].

于 2012-06-05T21:54:22.140 回答
0

如果一个 a structwhich 以所有相同类型的字段开头,则可以声明 aunion其中包括该类型的结构以及适当字段类型的数组。如果这样做,读取或写入数组的元素将读取或写入适当的结构成员。这种行为适用于我所知道的所有实现,并且我相信如果所有字段的大小相同,它是可移植的。

结构 quad_int {int n0; 诠释n1;诠释n2; 诠释 n3;}
union quad_int_union {结构对 p; 诠释 n[4];}

union quad_int_union my_thing;

my_thing.n[0] 与 my_thing.p.n0 同义
my_thing.n[1] 与 my_thing.p.n1 同义
等等

于 2012-06-06T07:09:23.353 回答