【问题标题】:Is there a way to provide a single macro function to return values of different types including nothing?有没有办法提供一个宏函数来返回不同类型的值,包括什么?
【发布时间】:2016-01-01 10:58:35
【问题描述】:

我创建了以下宏来锁定互斥体并返回(从调用此宏的函数中)以防锁定尝试失败。目前我已将其缩小到 2 个宏 - 一个用于从返回值的函数返回,与类型无关,另一个用于从不返回任何内容的函数返回(即 void)。

宏之外的代码(下)仅用于说明,与宏将用于的实际生产代码几乎没有关系。

#define MUTEX_LOCK()\
    {\
        if (pthread_mutex_lock(&mutex) != 0)\
        {\
            printf("Failed to lock mutex.\n");\
            return;\
        }\
    }
#define MUTEX_LOCK_RVAL(err_val)\
    {\
        if (pthread_mutex_lock(&mutex) != 0)\
        {\
            printf("Failed to lock mutex.\n");\
            return err_val;\
        }\
    }

void vfunc()
{
    printf("\nIn vfunc()\n");
    MUTEX_LOCK();
    printf("\nOut of vfunc()\n");
}

UINT16 uint16func()
{
    printf("\nIn uint16func()\n");
    MUTEX_LOCK_RVAL(0);
    printf("\nOut of uint16func()\n");

    return 9;
}

CHAR* errstr = "Hoo boy!";
CHAR* strfunc()
{
    printf("\nIn strfunc()\n");
    MUTEX_LOCK_RVAL(errstr);
    printf("\nOut of strfunc()\n");

    return NULL;
}

有没有办法将这些简化为一个宏,可以在返回值的函数中使用,也可以在 void 中使用。

【问题讨论】:

  • 包含返回的类似函数的宏......这真的很讨厌。算了,在调用点使用if (!my_lock()) return <whatever>;,有适当的锁定功能。
  • 可能使用例如variadic macros,但有一些警告。这真的会让你的代码的其他读者感到困惑(而“其他人”我会在一年左右的时间里将你包括在内)。
  • @JoachimPileborg 你认为调用会令人困惑,还是只有宏定义?如果只有后者,一些明智的 cmet 应该解决它,不是吗?
  • 哦,当您将pthread_mutex_lock 的返回值与未初始化的局部变量 进行比较时,您当前的宏包含未定义的行为。实际上你根本不需要变量,我真的建议你考虑一下@Mat 在说什么,然后你可以有一个简单的宏。
  • 你把打印放在了锁功能里,不用重复了。隐藏 return 语句不是如果唯一可以为您节省几次击键的事情。记住你写了一次代码,但读了很多次。如果这意味着您的函数的控制流已变得不可见,则保存几个字符是个坏主意。

标签: c c-preprocessor


【解决方案1】:

为了使其与 ANSI 兼容,我使用 return 和另一个简单的符号定义了宏,该符号的计算结果为 null 并清楚地表明它为 null。 即:

#define VOID_RET    //This nulls the return value
#define MUTEX_LOCK(err_val)\
    {\
        if (pthread_mutex_lock(&mutex) != 0)\
        {\
            printf("Failed to lock mutex.\n");\
            return err_val;\
        }\
    }
void *mutex = NULL;
void vfunc(void)
{
    printf("\nIn vfunc()\n");
    MUTEX_LOCK(VOID_RET);
    printf("\nOut of vfunc()\n");
}
UINT16 uint16func(void)
{
    printf("\nIn uint16func()\n");
    MUTEX_LOCK(0);
    printf("\nOut of uint16func()\n");

    return 9;
}
CHAR* errstr = "Hoo boy!";
CHAR* strfunc(void)
{
    printf("\nIn strfunc()\n");
    MUTEX_LOCK(errstr);
    printf("\nOut of strfunc()\n");

    return NULL;
}

我在 C11 和 C99 下测试了这段代码。

【讨论】:

  • 无论如何,这比我的解决方案要好得多。
【解决方案2】:

据我从文档中可以看出,您可以删除不带参数的宏函数,因为您根本没有义务将参数传递给需要参数的宏函数。
来自GNU GCC documentation

您可以将宏参数留空;这不是错误 预处理器 [...]


对于多个参数,这很有趣:

你不能完全忽略论点;如果一个宏需要两个 参数,其顶层必须有一个逗号 参数列表。

给出这些例子:

min(, b)        ==> ((   ) < (b) ? (   ) : (b))
min(a, )        ==> ((a  ) < ( ) ? (a  ) : ( ))
min(,)          ==> ((   ) < ( ) ? (   ) : ( ))
min((,),)       ==> (((,)) < ( ) ? ((,)) : ( ))

【讨论】:

  • 我试过这个,但这不是有效的 ansi C(我用 -pedantic 和 -Werror 标志编译)。我收到错误空宏参数在 ISO C90 和 ISO C++98 中未定义
  • @work.bin 你能告诉我你为什么要遵守这些旧标准吗?现在至少 C99 应该是默认的,IMO。
  • 如您所愿!但是支持 C99 的编译器并不多。如果便携性是一个问题,那么您仅限于 C90。
【解决方案3】:

我能想到的唯一解决方案是:

#define MUTEX_LOCK( err_val )\
{\
  {\
      if (pthread_mutex_lock(&mutex) != 0)\
      {\
          printf("Failed to lock mutex.\n");\
          return err_val;\
      }\
   }\
}

int test_int()
{
    MUTEX_LOCK( 1 );

    return 0;
}

void test_void()
{
    MUTEX_LOCK( ; );

    return;
}

【讨论】:

  • 不是特别优雅,但很聪明。这确实回答了我的问题,但我不确定我是否会使用它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-21
  • 1970-01-01
  • 1970-01-01
  • 2020-03-10
相关资源
最近更新 更多