2012-01-02 67 views
5

好吧,这可能听起来有点模糊的标题,但那是因为我不知道如何以不同的方式说出它。我将尝试解释我的意思:在某些库中,'init'函数经常接受一些参数,但该参数接受多个参数(右..)。举例来说,会是这样:C/C++中的单个参数(函数)中的多个参数

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); 

这是如何工作的?我无法在任何地方找到答案,很可能是因为我不知道它是如何被调用的,所以我不知道要搜索什么。这对我目前的项目非常有用。

在此先感谢!

+2

当你写它,它赢得了** 't **工作,因为你的标志没有设置不同的位。 – 2012-01-02 10:37:05

+0

这是我意识到的,它主要是为了举例的目的。原谅我,我现在还没有睡30个小时! :( – 2012-01-02 11:00:21

回答

5

第五个参数通常是一个掩码。它的工作原理是定义几个常量(可能是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 
    // .. 
} 
+0

这正是我需要知道的。非常感谢你,我有点像这样,但是在我浏览的任何源代码中找不到示例! – 2012-01-02 10:47:14

+0

不客气。 – Gorpik 2012-01-02 10:53:54

9

该参数通常称为“$ FOO标志”,值为or -ed。重点是该参数是一个数字类型,它构造为多个可能值的按位or

在处理功能,该值通常与按位and测试:

if ((flags & API_FULLSCREEN) != 0) 

你必须要小心,以在保持或操作线性的方式分配值。换句话说,不要在两个不同的or -able值中设置相同的位,就像您在标题中所做的那样。例如,

#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

+0

我最好在C中工作,所以我想这是我现在需要查看的方式。但是,我会看一看std :: bitset,因为很高兴知道这样的东西我会假设: 你的回答最有启发性,谢谢! – 2012-01-02 10:36:56

+0

我决定把另一个问题作为答案,因为它提供了一个更具体的例子,真的我想标记两个答案,所以我只想再次感谢你。 :) – 2012-01-02 10:54:32

+0

你的按位和'示例是不正确的。运算符优先级表示您需要圆括号才能得到预期的结果:'if((flags&API_FULLSCREEN)!= 0)'。 – ChrisN 2012-01-02 12:17:07

1

他们在那里做的是使用二进制OR将标志组合在一起。

那么,什么是实际发生的情况是:

0x10003003 | 0x10003004 | 0x10003005 == 0x10003007

它仍然是一个参数,但3位会结合起来,创造可在函数中使用该参数的唯一值。

+0

我觉得它会是这样的,但有几件事出现在我的脑海里。例如,如果两个标志的结果是相同的呢?你能否给出一个关于它如何工作的快速实例?我是否必须首先计算-every-可能性,然后进行切换(标志){/ *例如去这里* /} – 2012-01-02 10:33:42

+0

@JesseBrands程序员必须确保自己没有相同的值。所以是的,你必须用预先计算的标志值进行切换。 – Serdalis 2012-01-02 10:37:27

+1

@JesseBrands:标志必须是正交的,当然。对于一个位向量来说,这意味着每个标志只设置一个特定的位(也可能是一些非正交的掩码位,表示一组标志中的一个已被使用)。 – datenwolf 2012-01-02 11:18:40

1

从功能签名的角度来看,您定义为多参数的内容完全是单个参数。 至于基于单个参数处理多个Options,您可以看到有bitwise Or Operator它为参数值设置单个值。函数的主体然后使用各个位来确定完整的设置。

通常,一个位分配给一个选项,它们通常具有两个状态(真/假)值。

0

位或

位或工作几乎完全的方式按位与相同。唯一的区别是,结果中只有两个比特中的一个比特需要为1(如果两个比特都是1,那么结果在该位置也将为1)。符号是一个管道:|。再次,这与布尔逻辑运算符类似,即||。

01001000 | 10111000 = 11111000

因此 72 | 184 = 248

所以在你方法不是一个多参数它只是一个参数。 您可以在API_FULLSCREEN上使用按位或操作| API_NO_DELAY | API_BLAH_BLAH并在方法中传递它。

0

您提供的示例将无法按预期工作。你要做的就是使用特定位特定选项 - 然后

的OR结合实例

#define OPT1 1 
#define OPT2 2 
#define OPT3 4 

所以位1是OPT1,第2位是OPT2等

所以OPT1 | OPT3套位1和3,并给出了5

值在功能如果使用歌剧所需要的特定选项,您可以测试TOR

所以

void perform(int opts) 
{ 
if (opts & OPT1) 
{ 
// Do stuff for OPT1 
} 
... 
1

参数通常被称为“标志”,并包含一个组所允许值的或-ED组合。

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_ carfull *参数。

0

这些参数的值是以它们没有任何重叠的方式定义的。事情是这样的:

#define A 0x01 
#define B 0x02 
#define C 0x04 
#define D 0x08 

鉴于上述定义,你可以随时确定上述变量的已使用位AND操作OR编辑:

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; 
}