2012-01-02 66 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; 
}