首页 > 解决方案 > 在 c 复合语句中使用宏时

问题描述

我写了一个例子来说明我的问题,这里是使用嵌套宏来调用来检查数字是正数还是奇数。我知道使用这个调用是多余的,但正如我之前所说,它只是表明如果以嵌套方式使用宏,则会出现一些问题:

#include <stdio.h>
#include <stdlib.h>

#define num_is_positive_odd(num)                           \
({                                                         \
    int __rc = 0;                                          \
    int __num = (num);                                     \
                                                           \
    printf("%s:%d: check linenum\n", __func__, __LINE__);  \
    if (num_is_positive(__num) && num_is_odd(__num))       \
        __rc = 1;                                          \
    __rc;                                                  \
 })

#define num_is_positive(num)                  \
({                                            \
    int __rc = 0;                             \
    int __num = (num);                        \
                                              \
    if (__num > 0) {                          \
        printf("%s: number %d is positive\n", \
               __func__, __num);              \
        __rc = 1;                             \
    }                                         \
    __rc;                                     \
 })

#define num_is_odd(num)                       \
({                                            \
    int __rc = 0;                             \
    int __num = (num);                        \
                                              \
    if (__num / 2) {                          \
        printf("%s: number %d is odd\n",      \
               __func__, __num);              \
        __rc = 1;                             \
    }                                         \
    __rc;                                     \
 })



int main()
{
    int num = 4;

    if (num_is_positive_odd(num++))
        printf("%s: number %d is positive odd\n", __func__, num);

    exit(0);
}

使用命令编译时:gcc -Wunused-variable chk_comps.c

它显示错误:

chk_comps.c: In function ‘main’:
chk_comps.c:7:9: warning: unused variable ‘__num’ [-Wunused-variable]
     int __num = (num);                                     \
         ^
chk_comps.c:47:9: note: in expansion of macro ‘num_is_positive_odd’
     if (num_is_positive_odd(num++))
         ^

`

有人可以帮助解释为什么以及如何解决它吗?谢谢。

标签: cmacros

解决方案


这是使用称为语句表达式的 GCC 扩展——因此规则特定于 GCC(并且可能是 Clang 模拟 GCC)。

如果您运行gcc -E,您可以看到main()void由我添加)的原始输出是:

# 41 "gccm43.c"
int main(void)
{
    int num = 4;

    if (({ int __rc = 0; int __num = (num++); printf("%s:%d: check linenum\n", __func__, 45); if (({ int __rc = 0; int __num = (__num); if (__num > 0) { printf("%s: number %d is positive\n", __func__, __num); __rc = 1; } __rc; }) && ({ int __rc = 0; int __num = (__num); if (__num / 2) { printf("%s: number %d is odd\n", __func__, __num); __rc = 1; } __rc; })) __rc = 1; __rc; }))
        printf("%s: number %d is positive odd\n", __func__, num);
    return 0;
}

其中,当手动格式化(“炼狱”主题的变体)时,可能看起来像:

# 41 "gccm43.c"
int main(void)
{
    int num = 4;

    if (({ int __rc = 0;
           int __num = (num++);
           printf("%s:%d: check linenum\n", __func__, 45);
           if (({ int __rc = 0;
                  int __num = (__num);
                  if (__num > 0)
                  {
                      printf("%s: number %d is positive\n", __func__, __num);
                      __rc = 1;
                  }
                  __rc;
                }) &&
                ({ int __rc = 0; 
                   int __num = (__num);
                   if (__num / 2)
                   {
                       printf("%s: number %d is odd\n", __func__, __num);
                       __rc = 1;
                   }
                   __rc;
                 }
               ))
           __rc = 1;
           __rc;
         }
       ))
        printf("%s: number %d is positive odd\n", __func__, num);
    return 0;
}

线条int __num = (__num);有问题;您正在使用自身初始化变量,这并不能很好地完成(初始化前后的值是不确定的)。你还用来(__num / 2)判断是否__num是奇数,这是一种奇数检测奇数的方法;你应该使用(__num % 2).

现在也很明显为什么编译器会警告__num未使用(其中一个)(变量)。外部声明分配num++__num,但从不使用初始化变量,因为内部出现的int __num = (__num);引用自身而不是外部__num,因此使用。

你最好使用静态内联函数——像这样:

#include <stdio.h>
#include <stdlib.h>

static inline int num_is_positive(int num)
{
    int rc = 0;

    if (num > 0)
    {
        printf("%s: number %d is positive\n", __func__, num);
        rc = 1;
    }
    return rc;
}

static inline int num_is_odd(int num)
{
    int rc = 0;

    if (num % 2)        // BUG fixed
    {
        printf("%s: number %d is odd\n", __func__, num);
        rc = 1;
    }
    return rc;
}

static inline int num_is_positive_odd(int num)
{
    int rc = 0;

    printf("%s:%d: check linenum\n", __func__, __LINE__);
    if (num_is_positive(num) && num_is_odd(num))
        rc = 1;
    return rc;
}

int main(void)
{
    int num = 4;

    if (num_is_positive_odd(num++))
        printf("%s: number %d is positive odd\n", __func__, num);

    return 0;
}

推荐阅读