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。提供了一个写得很好且完整的答案。如果回答了您的问题,您应该将其标记为已接受,或者提供有关问题的更多信息/说明其不足之处。否则,由于没有任何答案被接受,因此它将仍然没有得到答复。