Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++预处理器按参数宏选择_C++_Preprocessor - Fatal编程技术网

C++预处理器按参数宏选择

C++预处理器按参数宏选择,c++,preprocessor,C++,Preprocessor,我试图定义一个预处理器宏,该宏根据参数的值依次选择正确的宏 #define BIT_8(n) n, "is lower or equal than 8" #define BIT_N(n) n, "is greater than 8" #define BIT(n) ????? int main() { printf("%d %s", BIT(9)); return 0; } BITn应扩展到: 如果为n,则为第8n位≤8. 如果n>8,则为位Nn 有什么方法可以做到这一点吗?除

我试图定义一个预处理器宏,该宏根据参数的值依次选择正确的宏

#define BIT_8(n) n, "is lower or equal than 8"
#define BIT_N(n) n, "is greater than 8"
#define BIT(n) ?????

int main() {
    printf("%d %s", BIT(9));
    return 0;
}
BITn应扩展到:

如果为n,则为第8n位≤8. 如果n>8,则为位Nn


有什么方法可以做到这一点吗?

除非您想要非常笨拙的代码,否则您无法做到这一点。预处理器不知道传入的参数的值。它只是替换字符串而已

也就是说,他们是为[0到63]中的所有x实现位_x的疯子。 这非常难看,如果参数设置为64,则会失败

一个干净的解决方案是使用函数:

const char * bit_msg(unsigned int b)
{
    if (b > 8) return "is greater than 8";
    const char * bits[] = {
"is 0 and lower than 8",
"is 1 and lower than 8",
"is 2 and lower than 8",
"is 3 and lower than 8",
"is 4 and lower than 8",
"is 5 and lower than 8",
"is 6 and lower than 8",
"is 7 and lower than 8",
"is 8",
}; 
return bits[b];
}

#define BIT(X) X, bit_msg(X)
[...]
printf("%d %s", BIT(9));

因为你已经用C++标记了这个问题,并且跟随@ RoMeN,你可以使用COSTEXPR获得相似的结果,如果可能的话,编译器将在编译时计算,从而得到与宏有效的代码。


在上面的示例中,您只需将签名替换为constexpr const char*bit\msgunsigned int b,编译器甚至可能跳过该函数并编写printf%d%s的等效值,9大于8。

除非您需要非常笨拙的代码,否则无法执行此操作。预处理器不知道传入的参数的值。它只是替换字符串而已

也就是说,他们是为[0到63]中的所有x实现位_x的疯子。 这非常难看,如果参数设置为64,则会失败

一个干净的解决方案是使用函数:

const char * bit_msg(unsigned int b)
{
    if (b > 8) return "is greater than 8";
    const char * bits[] = {
"is 0 and lower than 8",
"is 1 and lower than 8",
"is 2 and lower than 8",
"is 3 and lower than 8",
"is 4 and lower than 8",
"is 5 and lower than 8",
"is 6 and lower than 8",
"is 7 and lower than 8",
"is 8",
}; 
return bits[b];
}

#define BIT(X) X, bit_msg(X)
[...]
printf("%d %s", BIT(9));

因为你已经用C++标记了这个问题,并且跟随@ RoMeN,你可以使用COSTEXPR获得相似的结果,如果可能的话,编译器将在编译时计算,从而得到与宏有效的代码。 在上面的示例中,您只需将签名替换为constexpr const char*bit\msgunsigned int b,编译器甚至可能跳过该函数并编写printf%d%s的等效值,9大于8。

您可以这样做

#include <stdio.h>

#define BIT_8(n) printf("%d is lower than or equal to 8 \n" , n)
#define BIT_N(n) printf("%d is greater than 8 \n" , n)
#define BIT(n) ((n <= 8) ? (BIT_8(n)) : (BIT_N(n)))

int main() {
    BIT(7);
    BIT(8);
    BIT(9);
    return 0;
}
你可以这样做

#include <stdio.h>

#define BIT_8(n) printf("%d is lower than or equal to 8 \n" , n)
#define BIT_N(n) printf("%d is greater than 8 \n" , n)
#define BIT(n) ((n <= 8) ? (BIT_8(n)) : (BIT_N(n)))

int main() {
    BIT(7);
    BIT(8);
    BIT(9);
    return 0;
}

挑战在于预处理器不懂数学。你可以通过实现你需要的数学来解决这个问题,但它会变得难看。例如,下面是您要执行的操作的预处理器代码:

#include <stdio.h>

#define BIT_8(n) n, "is lower or equal than 8"
#define BIT_N(n) n, "is greater than 8"

// Identify values less than 8; make the second argument 8
#define LT_8_0 ~,8
#define LT_8_1 ~,8
#define LT_8_2 ~,8
#define LT_8_3 ~,8
#define LT_8_4 ~,8
#define LT_8_5 ~,8
#define LT_8_6 ~,8
#define LT_8_7 ~,8
#define LT_8_8 ~,8

// Helper macros.  Delays let arguments be processed before the macros is run.
#define MERGE(A, B) A ## B
#define MERGE_DELAY(A, B) MERGE(A,B)
#define ARG2(A,B,...) B
#define ARG2_DELAY(A,B,...) ARG2(A,B,__VA_ARGS__)

// Return 8 or N depending if n <= 8...
#define LT_8(n) ARG2_DELAY( MERGE(LT_8_, n), N,~ )

#define BIT(n) MERGE_DELAY(BIT_, LT_8(n))(n)

int main() {
  printf("%d %s\n", BIT(9));
  return 0;
}

请注意,LT_8宏通过获取一系列参数中的第二个参数来工作。我们将第二个参数默认为N,但如果我们识别出输入数字为8或更少,我们将插入一个新的第二个参数8。

挑战在于预处理器不懂数学。你可以通过实现你需要的数学来解决这个问题,但它会变得难看。例如,下面是您要执行的操作的预处理器代码:

#include <stdio.h>

#define BIT_8(n) n, "is lower or equal than 8"
#define BIT_N(n) n, "is greater than 8"

// Identify values less than 8; make the second argument 8
#define LT_8_0 ~,8
#define LT_8_1 ~,8
#define LT_8_2 ~,8
#define LT_8_3 ~,8
#define LT_8_4 ~,8
#define LT_8_5 ~,8
#define LT_8_6 ~,8
#define LT_8_7 ~,8
#define LT_8_8 ~,8

// Helper macros.  Delays let arguments be processed before the macros is run.
#define MERGE(A, B) A ## B
#define MERGE_DELAY(A, B) MERGE(A,B)
#define ARG2(A,B,...) B
#define ARG2_DELAY(A,B,...) ARG2(A,B,__VA_ARGS__)

// Return 8 or N depending if n <= 8...
#define LT_8(n) ARG2_DELAY( MERGE(LT_8_, n), N,~ )

#define BIT(n) MERGE_DELAY(BIT_, LT_8(n))(n)

int main() {
  printf("%d %s\n", BIT(9));
  return 0;
}

请注意,LT_8宏通过获取一系列参数中的第二个参数来工作。我们将第二个参数默认为N,但是如果我们识别出输入数字为8或更少,我们将插入一个新的第二个参数8。

确实不希望使用if constexpr吗?预处理器宏执行相当简单的文本替换。作为一种编程语言,预处理器是一个糟糕的选择。你确定不想使用if constexpr吗?预处理器宏执行相当简单的文本替换。作为一种编程语言,预处理器是一个糟糕的选择。我想补充一点,指出说明符可以用来将宏重写为可以在编译时计算的函数。理想情况下,现代C++代码不应该使用更多的预处理器。注意,如果使用令牌粘贴调用BIT9,那么对于所有X的实现BITYX都可以工作,它将失败为BIT8+。1@MartinBonner你完全正确。预处理器只是复制和粘贴,它不是一种语言。我想补充一点,指出可以使用说明符将宏重写为可在编译时计算的函数。理想情况下,现代C++代码不应该使用更多的预处理器。注意,如果使用令牌粘贴调用BIT9,那么对于所有X的实现BITYX都可以工作,它将失败为BIT8+。1@MartinBonner你完全正确。预处理器只是复制和粘贴,它不是一种语言。