【问题标题】:How to design my macro to contain function return value如何设计我的宏以包含函数返回值
【发布时间】:2019-02-20 12:24:38
【问题描述】:

为了避免问一个 X-Y 问题,我想先描述一下我的意图。自定义结构体有很多,都是静态单例变量。我想设计一个宏(或函数)来获得我想要的特定地址。到目前为止,这是我所做的:

/* the struct of apple, banana and cherry have been defined somewhere above
 * BUT NOT YET DECLARED */

const char *fruit_name[3] = {
    "apple",
    "banana",
    "cherry"
};

我的期望是用户可以简单地通过提供数字来获得指向struct的指针,即0获取到struct apple的ptr,1获取到structbanana的ptr等等。

我通过以下方式声明静态变量:

#define DEFSTRUCT(struct_name) \
    static struct struct_name my##struct_name(void)  \
    { \
        static struct strcut_name singleton;  \
        return &singleton; \
    }

然后我用它生成 3 个函数,这些函数将返回指向结构的指针:

DEFSTRUCT(apple)    // whenever calls myapple() I got the reference to static struct apple 
DEFSTRUCT(banana)
DEFSTRUCT(cherry)

最令人沮丧的部分来了,我无法制作宏(或函数)来传输字符串以访问它们

这就是我所做的,但徒劳无功:

#define GETSTRUCT(struct_name) my##struct_name()

void get_fruit(void *ptr, int num) {
    ptr = GETSTRUCT(fruit_name[num]);  // I expect that ptr would points to static struct apple if num is 0;
}

无论我多么努力,fruit_name[num] 都不会转换为正确的字符串名称, 有没有人可以指定我犯了什么错误? 非常感谢

【问题讨论】:

  • 这整件事仍然是一个 XY 问题。不是 100% 清楚你想在这里问什么,但这没有任何意义,所以你的问题是 Y 部分。您试图通过这些单例和按数字访问来解决的总体问题是什么? (为什么是数字?)
  • 您在 DEFSTRUCT 宏 (strcut_name) 中拼错了 struct_namereturn &singleton; 是类型错误。 get_fruit 没有做任何事情:分配给 ptr 是没有意义的,因为它是一个局部变量(即在函数返回时被销毁)。
  • 您的问题可以通过以下方式解决:static struct apple apple_singleton; static struct banana banana_singleton; static struct cherry cherry_singleton; static void *const fruit_mapping[] = { &apple_singleton, &banana_singleton, &cherry_singleton }; void *get_fruit(int n) { return fruit_mapping[n]; }
  • “苹果、香蕉和樱桃的结构已在上面某处定义但尚未声明”的评论没有意义。定义就是声明。也许这条评论应该说struct 类型已定义,但它的apple、banana 和cherry 实例尚未声明或定义。但是,这在代码中并不相关,因为以下代码仅声明了一个指向字符串的指针数组;不涉及struct

标签: c function macros


【解决方案1】:

函数参数num 不能在宏扩展中扩展为它的值,strings 数组的元素不能在宏扩展中扩展为它的字符串。这两个都需要在预处理器中从未发生过的评估。

返回结构指针的函数可以是:

struct struct_name *get_fruit(void *pointer, int index)
{
    static struct struct_name ArrayOfTheseThings[] =
    {
        { contents of "apple" struct },
        { contents of "banana" struct },
        { contents of "cherry" struct },
    };

    return &ArrayOfTheseThings[index];
}

或:

struct struct_name *get_fruit(void *pointer, int index)
{
    const static struct struct_name *ArrayOfPointers[] =
    {
        &NameOfAppleStructDefinedElsewhere;
        &NameOfBananaStructDefinedElsewhere;
        &NameOfCherryStructDefinedElsewhere;
    };

    return ArrayOfPointers[index];
}

【讨论】:

  • 感谢您的回复,但我想问一下您的第二个示例中的“struct struct_name”是什么意思?我不应该改用 const static void * 吗?因为这三种水果都有完全不同的数据类型
  • @Shih-ChanHuang: ArrayOfPointers 可以变成void * 的数组,get_fruit 可以返回void *。但是,这增加了您遇到 X-Y 问题的迹象。返回 void * 对于不知道所指向对象类型的调用者来说基本上是无用的。换句话说,调用者需要知道他们是否有struct applestruct banana 或其他东西,如果他们要对指针做任何事情而不是比较它或将它传递给其他软件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多