有没有办法提供一个宏函数来返回不同类型的值,包括啥?

Posted

技术标签:

【中文标题】有没有办法提供一个宏函数来返回不同类型的值,包括啥?【英文标题】: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 语句不是如果唯一可以为您节省几次击键的事情。记住你写了一次代码,但读了很多次。如果这意味着您的函数的控制流已变得不可见,则保存几个字符是个坏主意。 【参考方案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;

【讨论】:

不是特别优雅,但很聪明。这确实回答了我的问题,但我不确定我是否会使用它。

以上是关于有没有办法提供一个宏函数来返回不同类型的值,包括啥?的主要内容,如果未能解决你的问题,请参考以下文章

关于宏函数的返回值

请问函数的返回值类型那里,写“类名”和“类名&”有啥区别?

matlab 中norm函数是啥意思

请问函数的返回值类型那里,写“类名”和“类名&”有啥区别?

布尔类型是啥意思?

返回布尔值的 Perl 函数实际上返回啥