C 使用#define定义结构对象

C 使用#define定义结构对象,c,c-preprocessor,C,C Preprocessor,我在某处遇到了这个简单的程序 #include<stdio.h> #include<stdlib.h> char buffer[2]; struct globals { int value; char type; long tup; }; #define G (*(struct globals*)&buffer) int main () { G.value = 233; G.type = '*';

我在某处遇到了这个简单的程序

#include<stdio.h>
#include<stdlib.h>

char buffer[2];
struct globals {

  int value;
  char type;
  long tup;

};

#define G (*(struct globals*)&buffer)

int main ()
{
        G.value = 233;
        G.type = '*';
        G.tup = 1234123;

        printf("\nValue = %d\n",G.value);
        printf("\ntype = %c\n",G.type);
        printf("\ntup = %ld\n",G.tup);

        return 0;
}
我不确定define G语句是如何工作的。
如何将G定义为struct globals类型的对象

宏只是将两个字符的缓冲区
buf
的地址强制转换为指向相应结构类型的指针,然后取消引用该指针以生成结构类型的左值。这就是点(
)结构访问操作符在
G
上工作的原因

不知道为什么会有人这么做。我认为在需要时转换字符数组(在示例代码中是“从不”,但可能在较大的原始代码库中的某个地方使用),或者使用
联合
来摆脱宏,会更干净

union {
  struct {
   int value;
   /* ... */
  } s;
  char c[2];
} G;

G.s.value = 233;  /* and so on */

它既干净又清晰。请注意,
char
数组太小。

宏只是将两个字符的缓冲区
buf
的地址强制转换为指向相应结构类型的指针,然后取消引用该结构类型以生成结构类型的左值。这就是点(
)结构访问操作符在
G
上工作的原因

不知道为什么会有人这么做。我认为在需要时转换字符数组(在示例代码中是“从不”,但可能在较大的原始代码库中的某个地方使用),或者使用
联合
来摆脱宏,会更干净

union {
  struct {
   int value;
   /* ... */
  } s;
  char c[2];
} G;

G.s.value = 233;  /* and so on */

它既干净又清晰。请注意,
char
数组太小。

首先,此代码具有未定义的行为,因为它将双字节数组重新解释为更大的
结构。因此,它正在写入已分配空间的末尾。通过使用
struct
的大小声明
buffer
数组,可以使程序有效,如下所示:

struct globals {
    int value;
    char type;
    long tup;    
};
char buffer[sizeof(struct globals)];
#define
以其通常的方式工作-通过提供标记
G
的文本替换,就像您在最喜爱的文本编辑器中运行搜索和替换一样。预处理器是C编译器的第一阶段,它查找每个条目
G
,并将其替换为
(*(struct globals*)&buffer)

预处理器完成后,编译器将看到以下代码:

int main ()
{
    (*(struct globals*)&buffer).value = 233;
    (*(struct globals*)&buffer).type = '*';
    (*(struct globals*)&buffer).tup = 1234123;

    printf("\nValue = %d\n",(*(struct globals*)&buffer).value);
    printf("\ntype = %c\n",(*(struct globals*)&buffer).type);
    printf("\ntup = %ld\n",(*(struct globals*)&buffer).tup);

    return 0;
}

首先,此代码具有未定义的行为,因为它将双字节数组重新解释为更大的
struct
。因此,它正在写入已分配空间的末尾。通过使用
struct
的大小声明
buffer
数组,可以使程序有效,如下所示:

struct globals {
    int value;
    char type;
    long tup;    
};
char buffer[sizeof(struct globals)];
#define
以其通常的方式工作-通过提供标记
G
的文本替换,就像您在最喜爱的文本编辑器中运行搜索和替换一样。预处理器是C编译器的第一阶段,它查找每个条目
G
,并将其替换为
(*(struct globals*)&buffer)

预处理器完成后,编译器将看到以下代码:

int main ()
{
    (*(struct globals*)&buffer).value = 233;
    (*(struct globals*)&buffer).type = '*';
    (*(struct globals*)&buffer).tup = 1234123;

    printf("\nValue = %d\n",(*(struct globals*)&buffer).value);
    printf("\ntype = %c\n",(*(struct globals*)&buffer).type);
    printf("\ntup = %ld\n",(*(struct globals*)&buffer).tup);

    return 0;
}

您的
缓冲区
太小,其长度应至少为
sizeof(struct globals)
@user28264。这里提供了一个写得很好且完整的答案。如果回答了您的问题,您应该将其标记为已接受,或者提供有关问题的更多信息/说明其不足之处。否则,由于未接受任何答案,因此它将保持为未回答。您的
缓冲区
太小,其长度应至少为
sizeof(struct globals)
@user28264。提供了一个写得很好且完整的答案。如果回答了您的问题,您应该将其标记为已接受,或者提供有关问题的更多信息/说明其不足之处。否则,由于没有任何答案被接受,因此它将仍然没有得到答复。