好吧这可能听起来有点含糊不清,但那是因为我不知道如何用不同的方式来表达它。我将尝试解释我的意思:通常在某些库中,'init'函数接受一些参数,但该参数接受多个参数(右..)。一个例子,就像这样:
apiHeader.h
#define API_FULLSCREEN 0x10003003
#define API_NO_DELAY 0x10003004
#define API_BLAH_BLAH 0x10003005
main.c中:
apiInit(0, 10, 10, 2, API_FULLSCREEN | API_NO_DELAY | API_BLAH_BLAH);
这是如何工作的?我无法在任何地方找到答案,很可能因为我不知道它是如何实际调用的,所以我不知道要搜索什么。这在我目前的项目中非常有用。
提前致谢!
答案 0 :(得分:9)
该参数通常称为“$ FOO flags”,值为or
- ed。关键是参数是一个数值类型,构造为多个可能值的按位or
。
在处理函数中,通常使用按位and
:
if ( (flags & API_FULLSCREEN) != 0 )
您必须小心以保持OR运算线性的方式分配值。换句话说,不要像在标题中那样在两个不同的or
个值中设置相同的位。例如,
#define API_FULLSCREEN 0x1
#define API_NO_DELAY 0x2
#define API_BLAH_BLAH 0x4
工作并允许您解析函数中的所有标志组合,但
#define API_FULLSCREEN 0x1
#define API_NO_DELAY 0x2
#define API_BLAH_BLAH 0x3
不是因为API_FULLSCREEN | API_NO_DELAY == API_BLAH_BLAH
。
从更高级别查看,flags int是一个穷人的变量参数列表。如果您考虑使用C ++,则应将此类详细信息封装在一个类中,或至少包含std::bitset
。
答案 1 :(得分:6)
这第五个参数通常是一个掩码。它的工作原理是定义几个consts(可能是enum
),其值为2的幂或它们的组合。然后使用|
将它们编码为单个值,并使用&
进行解码。例如:
#define COLOUR_RED 0x01
#define COLOUR_GREEN 0x02
#define COLOUR_BLUE 0x04
#define COLOUR_CYAN (COLOUR_BLUE | COLOUR_GREEN) // 0x06
// Encoding
SetColour(COLOUR_RED | COLOUR_BLUE); // Parameter is 0x05
// Decoding
void SetColour(int colour)
{
if (colour & COLOUR_RED) // If the mask contains COLOUR_RED
// Do whatever
if (colour & COLOUR_BLUE) // If the mask contains COLOUR_BLUE
// Do whatever
// ..
}
答案 2 :(得分:1)
他们正在做的是使用二进制OR
将标志组合在一起。
所以实际发生的是:
0x10003003 | 0x10003004 | 0x10003005 == 0x10003007
它仍然是一个参数,但是3个标志将组合起来为该参数创建一个可以在函数中使用的唯一值。
答案 3 :(得分:1)
从函数签名的角度来看,您定义的多个参数严格来说是一个参数。
至于基于单个参数处理多个Options
,正如您所看到的,bitwise Or Operator
为参数值设置了单个值。然后,函数体使用各个位来确定完整设置。
通常,为一个选项分配一个位,它们通常有两个状态(真/假)值。
答案 4 :(得分:1)
该参数通常称为“标志”,包含一组允许值的或组合。
int flags = API_FULLSCREEN | API_NO_DELAY;
该函数可以获取此整数参数并提取单个项目,如下所示:
int fullscreen_set = flags & API_FULLSCREEN;
int no_delay_set = flags & API_NO_DELAY;
int blah_blah_set = flags & API_BLAH_BLAH;
为了实现这个目的,我必须在选择API_ *参数的数值方面做得很好。
答案 5 :(得分:0)
按位OR
按位OR的工作方式与按位AND几乎完全相同。唯一的区别是两个位中只有一个需要为1,因为结果中该位的位为1.(如果两个位都为1,则结果在该位置也将为1。)符号为管道:|。同样,这类似于布尔逻辑运算符,它是||。
01001000 | 10111000 = 11111000
因此 72 | 184 = 248
所以你的方法不是一个多参数,它实际上是一个参数。 您可以在API_FULLSCREEN |上使用按位或操作API_NO_DELAY | API_BLAH_BLAH并在方法中传递它。
答案 6 :(得分:0)
您提供的示例将无法按预期工作。你所做的是为特定选项使用特定位 - 然后OR合并
示例强>
#define OPT1 1
#define OPT2 2
#define OPT3 4
因此,第1位用于OPT1,第2位用于OPT2等。
因此OPT1 | OPT3
设置第1位和第3位并给出值5
在该功能中,您可以使用 AND 运算符测试是否需要特定选项
所以
void perform(int opts)
{
if (opts & OPT1)
{
// Do stuff for OPT1
}
...
答案 7 :(得分:0)
这些参数的值以它们没有任何重叠的方式定义。像这样:
#define A 0x01
#define B 0x02
#define C 0x04
#define D 0x08
鉴于上述定义,您始终可以使用按位OR
运算符确定上述哪些变量AND
:
void foo(int param)
{
if(param & A)
{
// then you know that A has been included in the param
}
if(param & B)
{
// then you know that B has been included in the param
}
...
}
int main()
{
foo (A | C);
return 0;
}