2012-01-02 42 views
5

Ok điều này nghe có vẻ hơi mơ hồ trong tiêu đề, nhưng đó là vì tôi không biết cách viết nó theo cách khác. Tôi sẽ cố gắng giải thích ý tôi: rất thường xuyên trong một số thư viện, hàm 'init' chấp nhận một số tham số, nhưng tham số đó sau đó chấp nhận nhiều tham số (phải ..). Một ví dụ, sẽ là như thế này:Nhiều tham số trong một tham số (chức năng) trong 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); 

làm việc như thế này? Tôi không thể tìm thấy câu trả lời ở bất cứ đâu, rất có thể vì tôi không biết nó được gọi như thế nào nên tôi không biết phải tìm kiếm gì. Nó sẽ rất hữu ích trong dự án hiện tại của tôi.

Cảm ơn trước!

+2

Như bạn đã viết nó, nó ** thắng 't ** làm việc, vì cờ của bạn không thiết lập các bit khác nhau. –

+0

Đây là tôi nhận ra, nó chủ yếu là cho các mục đích ví dụ. Tha thứ cho tôi, tôi đã không ngủ trong 30 giờ! :( –

Trả lời

5

Thông số thứ năm này thường là mặt nạ. Nó hoạt động bằng cách xác định một số const (có thể là enum) với các giá trị là sức mạnh của hai hoặc kết hợp chúng. Sau đó, chúng được mã hóa thành một giá trị sử dụng | và được giải mã bằng cách sử dụng &. Ví dụ:

#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

Đây chính xác là những gì tôi cần biết. Cảm ơn bạn rất nhiều, tôi kinda _figured_ nó là một cái gì đó như thế này, nhưng tôi không thể tìm thấy một ví dụ trong bất kỳ mã nguồn tôi duyệt! –

+0

Bạn được chào đón. – Gorpik

9

Thông số thường được gọi là "$ FOO flags" và các giá trị là or -ed. Vấn đề là tham số là kiểu số được xây dựng dưới dạng bitwise or của nhiều giá trị có thể.

Trong chức năng xử lý, các giá trị thường được thử nghiệm với một Bitwise and:

if ((flags & API_FULLSCREEN) != 0) 

Bạn phải cẩn thận để gán giá trị theo một cách mà giữ OR tuyến tính hoạt động. Nói cách khác, không đặt cùng một bit trong hai giá trị khác nhau or-có thể, giống như bạn đã làm trong tiêu đề của mình. Ví dụ,

#define API_FULLSCREEN 0x1 
#define API_NO_DELAY  0x2 
#define API_BLAH_BLAH 0x4 

công trình và cho phép bạn mổ xẻ tất cả các kết hợp của cờ trong chức năng của bạn, nhưng

#define API_FULLSCREEN 0x1 
#define API_NO_DELAY  0x2 
#define API_BLAH_BLAH 0x3 

không vì API_FULLSCREEN | API_NO_DELAY == API_BLAH_BLAH.

Xem từ cấp cao hơn, cờ int là danh sách đối số biến của người nghèo. Nếu bạn xem xét C++, bạn nên đóng gói chi tiết đó trong một lớp hoặc ít nhất là std::bitset.

+0

Tôi nên làm việc trong C, vì vậy tôi đoán đây là cách tôi sẽ phải tìm kiếm ngay bây giờ. Tuy nhiên, tôi sẽ có một cái nhìn tại std :: bitset, vì nó là tốt để biết những thứ như tôi sẽ Câu trả lời của bạn là sự khai sáng nhất, cảm ơn bạn –

+0

Tôi đã quyết định đánh dấu câu hỏi khác là câu trả lời, vì nó đã cung cấp một ví dụ hữu hình hơn Tôi thực sự muốn đánh dấu cả hai câu trả lời, vì vậy tôi chỉ muốn cảm ơn bạn một lần nữa. :) –

+0

Ví dụ 'và' bitwise của bạn không chính xác. Ưu tiên toán tử có nghĩa là bạn cần dấu ngoặc đơn để có được kết quả mong muốn: 'if ((flags & API_FULLSCREEN)! = 0)'. – ChrisN

1

Những gì họ đang làm ở đó đang sử dụng nhị phân OR để kết hợp các cờ với nhau.

vì vậy những gì đang thực sự xảy ra là:

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

Nó vẫn còn một tham số, nhưng 3 lá cờ sẽ kết hợp để tạo ra một giá trị duy nhất cho rằng tham số có thể được sử dụng trong hàm.

+0

Tôi đã hình dung nó giống như vậy, nhưng một vài điều nảy sinh trong đầu tôi. Ví dụ, nếu kết quả của hai lá cờ sẽ giống nhau? Có lẽ bạn có thể đưa ra một ví dụ thực tế nhanh chóng-n-bẩn về cách thức hoạt động này? Tôi sẽ phải tính toán -every- khả năng đầu tiên và sau đó làm một chuyển đổi (cờ) {/ * trường hợp đi đây * /} –

+0

@ JesseBrands Các lập trình viên sẽ phải đảm bảo rằng không có giá trị giống hệt nhau. Vì vậy, có bạn sẽ phải làm một chuyển đổi với các giá trị flag precomputed. – Serdalis

+1

@JesseBrands: Cờ phải là trực giao tất nhiên. Đối với một bit bit, điều này có nghĩa, mỗi cờ đặt chính xác một bit cụ thể (và có thể một số bit mặt nạ nonorthogonal để chỉ ra rằng một trong một nhóm cờ đã được sử dụng ở tất cả). – datenwolf

1

Điều bạn định nghĩa là nhiều tham số đúng là một tham số duy nhất từ ​​điểm chữ ký chức năng của chế độ xem. Đối với việc xử lý nhiều Options dựa trên một tham số duy nhất, như bạn có thể thấy có bitwise Or Operator đặt một giá trị duy nhất cho giá trị tham số. Phần thân của hàm sau đó sử dụng các bit riêng lẻ để xác định các thiết lập hoàn chỉnh.

Thông thường, một bit được phân bổ cho một tùy chọn và chúng thường có hai giá trị trạng thái (đúng/sai).

0

Bitwise OR

Bitwise OR hoạt động gần như chính xác theo cùng một cách như Bitwise AND. Sự khác biệt duy nhất là chỉ một trong hai bit cần phải là 1 cho bit của vị trí đó trong kết quả là 1. (Nếu cả hai bit là 1, kết quả cũng sẽ có 1 ở vị trí đó.) Biểu tượng là một đường ống: |. Một lần nữa, điều này tương tự như toán tử logic logic, là ||.

01001000 | 10111000 = 11111000

và do đó 72 | 184 = 248

Vì vậy, Trong phương pháp bạn không phải là một tham số nhiều, nó là một tham số actully. bạn có thể sử dụng Bitwise OR opearation trên API_FULLSCREEN | API_NO_DELAY | API_BLAH_BLAH và chuyển nó theo phương thức.

0

Ví dụ bạn đưa ra sẽ không hoạt động như mong đợi. Những gì bạn làm là sử dụng một chút đặc biệt đối với một lựa chọn đặc biệt - và OR kết hợp sau đó

Ví dụ

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

Vì vậy, cắn 1 là dành cho OPT1, cắn 2 là dành cho OPT2, vv

Vì vậy OPT1 | OPT3 bộ cắn 1 và 3 và đưa ra một giá trị của 5

trong chức năng bạn có thể kiểm tra nếu một lựa chọn đặc biệt được yêu cầu sử dụng opera tor

Vì vậy

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

Tham số này thường được gọi là "cờ" và chứa một kết hoặc-ed một tập hợp các giá trị được phép.

int flags = API_FULLSCREEN | API_NO_DELAY; 

Các chức năng có thể các tham số số nguyên này và trích xuất các mặt hàng cá nhân như thế này:

int fullscreen_set = flags & API_FULLSCREEN; 
int no_delay_set = flags & API_NO_DELAY; 
int blah_blah_set = flags & API_BLAH_BLAH; 

Để làm việc này người ta phải carfull trong cách người ta chọn các giá trị số cho API_ * thông số.

0

Giá trị của các thông số này được xác định theo cách mà chúng không có bất kỳ trùng lặp nào.Một cái gì đó như thế này:

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

Với các định nghĩa ở trên, bạn luôn có thể xác định các biến trên đã được OR ed sử dụng toán tử Bitwise 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; 
} 
Các vấn đề liên quan