2009-12-29 25 views
7

Được rồi, tôi đã thấy nhiều bài đăng ở đây về các thành ngữ kỳ lạ và thông lệ phổ biến trong C có thể không trực quan ban đầu. Có lẽ một vài ví dụ là đểThành ngữ C và ít sự kiện đã biết

yếu tố trong một mảng:

#define ELEMENTS(x) (sizeof (x)/sizeof (*(x))) 

Odd array indexing:

a[5] = 5[a] 

Single line if/else/while/for safe #defines

#define FOO(X) do { f(X); g(X); } while (0) 
#define FOO(X) if (1) { f(X); g(X); } else 

Câu hỏi của tôi để các chuyên gia C lập trình viên trên mạng là: Điều gì thành ngữ, thực hành, đoạn mã hoặc ít sự kiện đã biết hiển thị nhiều mã C nhưng có thể không trực quan nhưng cung cấp thông tin chi tiết về lập trình C?

+6

nên là cộng đồng wiki –

+0

Quá xấu nó đã bị đóng, bot không phải là một câu hỏi ... –

Trả lời

11

Các "mũi tên điều hành" cho đếm ngược từ n-1-0:

for (int i = n; i --> 0;) ... 

Đó không phải là vô cùng phổ biến, nhưng nó là một minh họa thú vị mà trong một số cách các phần khởi tạo/kiểm tra/cập nhật của một for vòng lặp là quy ước. Đó là mô hình thông thường, nhưng bạn vẫn có thể đặt bất kỳ biểu thức tùy ý nào trong đó.

Đó cũng là lời nhắc nhở nhỏ về cách phân tích từ vựng hoạt động.

+0

http://cplusplus.co.il/2009/12/28/the-omnipotent-arrow-operator/ – rmn

+0

Có chỉ đơn giản là không thoát khỏi nhà điều hành hùng mạnh này. – GManNickG

+0

Tốt cho tìm kiếm tuyến tính. Sau khi tất cả, nơi đầu tiên bạn nên xem là nơi cuối cùng bạn đặt một cái gì đó. –

4

Toán tử dấu phẩy, trong khi được ghi lại hoàn toàn (K & R, v.v.) xuất hiện khá nhiều mã thuật toán và thường gây ngạc nhiên cho nhiều lập trình viên không gặp phải trước đó. Nó thường được sử dụng để đơn giản hóa một số cấu trúc vòng lặp:

#define kITERATIONS_MAX 10 
int i=0,j=0,array[kITERATIONS_MAX],outArray[kITERATIONS_MAX],temp=0; 

for (i=0,j=kITERATIONS_MAX-1; i < kITERATIONS_MAX; i++,j--) 
{ 
temp = array[i]*array[j]; 
outArray[i]=temp; 
} 

Mã trên sẽ nhân các phần tử mảng 0 đến 9 với 9 qua 0 trong khi tránh các vòng lồng nhau.

Khi sử dụng toán tử dấu phẩy, cả biểu thức thứ nhất và thứ hai đều được đánh giá. Kết quả của biểu thức đầu tiên bị bỏ qua và kết quả của biểu thức thứ hai được trả về.

+0

Tôi sử dụng toán tử dấu phẩy trong các điều kiện 'while' làm hai việc, thường là gán theo sau bởi một phép thử:' while (c = getc(), c! = EOF) ... '. –

+0

@DavidRTribble Các 'c = getc()' đánh giá bằng với 'c', có nghĩa là bạn chỉ có thể (có lẽ) sử dụng' while ((c = getc())! = EOF) ...' –

+0

@RobbieMckennie, Đó là sự thật, nhưng tôi thấy nó dễ dàng hơn để đọc hai hoạt động (phân công và so sánh) như hai biểu thức riêng biệt trong biểu thức' while' điều khiển. –

5

Vì ai đó sẽ đề cập đến nó, nó cũng có thể là tôi: Duff's Device. Đó là một minh họa tốt đẹp về cách nhãn hoạt động trong C, và sự hiểu biết nó đã cho tôi một "trải nghiệm aha" lần đầu tiên. Đây là mã ban đầu của anh ấy:

send(to, from, count) 
register short *to, *from; 
register count; 
{ 
    register n=(count+7)/8; 
    switch(count%8){ 
    case 0: do{ *to = *from++; 
    case 7:  *to = *from++; 
    case 6:  *to = *from++; 
    case 5:  *to = *from++; 
    case 4:  *to = *from++; 
    case 3:  *to = *from++; 
    case 2:  *to = *from++; 
    case 1:  *to = *from++; 
     }while(--n>0); 
    } 
} 

Hôm nay, người ta sẽ không sử dụng register và tránh định nghĩa chức năng kiểu cũ.

+0

Ngoài ra, như tôi hiểu nó, bạn không muốn làm điều này trên một trình biên dịch tối ưu hóa hiện đại --- bạn sẽ chỉ nhận được theo cách của nó. – dubiousjim

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