【问题标题】:using #define for defining struct objects使用#define 定义结构对象
【发布时间】:2014-04-28 10:14:13
【问题描述】:

我在某处偶然发现了这个简单的程序

#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;
}

它正在编译(使用 gcc)并且执行良好,我得到以下输出:

Value = 233
type = *
tup = 1234123

我不确定#define G 语句是如何工作的。 G 如何定义为 struct globals 类型的对象?

【问题讨论】:

  • 您的buffer 太小,长度至少应为sizeof(struct globals)
  • @user28264 提供了一个写得很好的和彻底的答案。如果它回答了您的问题或提供有关问题的更多信息/说明为什么它还不够,您应该将其标记为已接受。否则它将保持未答复状态,因为没有接受任何答案。

标签: c c-preprocessor


【解决方案1】:

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

struct globals {
    int value;
    char type;
    long tup;    
};
char buffer[sizeof(struct globals)];

#define 以通常的方式工作 - 通过提供标记 G 的文本替换,就像您在最喜欢的文本编辑器中运行搜索和替换一样。预处理器,C 编译器的第一阶段,查找每个条目 G,并将其替换为 (*(struct globals*)&amp;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;
}

【讨论】:

    【解决方案2】:

    宏简单地将 2 字符缓冲区 buf 的地址转换为指向适当结构类型的指针,然后取消引用以生成结构类型的左值。这就是为什么点 (.) 结构访问运算符适用于 G

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

    union {
      struct {
       int value;
       /* ... */
      } s;
      char c[2];
    } G;
    
    G.s.value = 233;  /* and so on */
    

    既干净又清晰。注意char 数组太小了。

    【讨论】:

      猜你喜欢
      • 2020-10-03
      • 2016-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-11
      相关资源
      最近更新 更多