2012-02-29 35 views
13

thể trùng lặp:
Why are there sometimes meaningless do/while and if/else statements in C/C++ macros?Tại sao nên sử dụng {} khi (0) trong định nghĩa macro?

tôi gặp mã như dưới đây:

#define ev_io_init(ev,cb,fd,events) \ 
do { \ 
    ev_init ((ev), (cb)); \ 
    ev_io_set ((ev),(fd),(events)); \ 
} while (0) 

Tôi muốn biết lý do tại sao tác giả sử dụng do { } while (0) đây. Có sự khác biệt nào với điều này không?

#define ev_io_init(ev,cb,fd,events) { \ 
    ev_init ((ev), (cb)); \ 
    ev_io_set ((ev),(fd),(events)); \ 
} 

BTW: mã là từ libev, ev_local.h

Trả lời

10

Một do{}while(0) cho phép bạn phá vỡ từ loop:

do{ 
    expr1; 
    foo(); 
    if (cond) 
     break; 
    expr2; 
    goo(); 
} while (0); 

Nó giống như một khối đơn giản {...} ngoại trừ việc bạn có thể ngắt kết nối khi bạn muốn với câu lệnh break. Bạn không thể làm điều đó trong một khối mã đơn giản, trừ khi bạn có nhiều kiểm tra, mà có thể nhận được cồng kềnh. Nó vẫn được thực hiện một lần, vì điều kiện while(0).

+8

... nó làm, nhưng xin đừng ... – moonshadow

+0

Nó làm giảm số lượng các tổ if-else . – shuva

15

Mã kèm theo với vòng lặp cho phép chỉ thị tiền xử lý thực thi nhiều câu lệnh mà không cần "phá vỡ" if-else-construct. Hãy xem xét những điều sau:

#define DO_SOMETHING() a();b();c(); 

void foo() 
{ 
    // This is ok... 
    DO_SOMETHING(); 
} 

void bar() 
{ 
    // ...whereas this would trigger an error. 
    if (condition) 
     DO_SOMETHING(); 
    else 
     blah(); 
} 

Ví dụ thứ hai phá vỡ if-else-construct vì ba câu lệnh được theo sau bởi mệnh đề else. Để cho phép thay thế chính xác, các hướng dẫn trong DO_SOMETHING phải được đính kèm với do { ... } while(0).

+3

tất nhiên, nếu bạn sử dụng naked nếu các dòng như thế, bạn xứng đáng cho mã của bạn để phá vỡ ... – Simon

+2

@Simon Nhưng không linux hạt nhân mã hóa phong cách tư vấn cho chúng tôi sử dụng nude nếu khác dòng cho một khối dòng? https://www.kernel.org/doc/Documentation/CodingStyle – CoderSpinoza

+2

@CoderSpinoza dường như vậy, và nếu tôi làm việc trên hạt nhân Linux thì tôi sẽ làm theo kiểu đó. Ở những nơi khác, tôi muốn tránh nó. – Simon

23

Cân nhắc if(something) function1(); else function2();

Nếu function1() thực sự là một vĩ mô, chỉ sử dụng { } đòi hỏi bạn phải bỏ qua các dấu chấm phẩy tại thời điểm sử dụng, nhưng do { } while(0) cho phép bạn sử dụng chính xác cú pháp tương tự như đối với một chức năng thực sự.

(Không sử dụng bất kỳ loại khối xây dựng ở tất cả sẽ chỉ tạo ra mã hoàn toàn bị hỏng, natch)

Các vấn đề liên quan