Lạm dụng tiền xử lý / tiền xử lý trong thế giới thực tồi tệ nhất bạn từng gặp là gì?


176

Có gì là tồi tệ nhất thế giới thực macro / pre-processor lạm dụng bạn đã từng đi qua (xin đừng contrived IOCCC câu trả lời * haha *)?

Vui lòng thêm một đoạn ngắn hoặc câu chuyện nếu nó thực sự mang tính giải trí. Mục tiêu là dạy một cái gì đó thay vì luôn nói với mọi người "không bao giờ sử dụng macro".


ps: Trước đây tôi đã sử dụng macro ... nhưng thường thì cuối cùng tôi cũng thoát khỏi chúng khi tôi có giải pháp "thực" (ngay cả khi giải pháp thực sự được nội tuyến để nó trở nên giống với macro).


Phần thưởng: Cho một ví dụ trong đó macro thực sự tốt hơn giải pháp không vĩ mô.

Câu hỏi liên quan: Khi nào các macro C ++ có lợi?


+1 vì đã gây chú ý đến sự lạm dụng tràn lan mà tôi đã phải chịu trong tay của Macros.
i_am_jorf 17/03/2016

37
#define đúng sai // gỡ lỗi hạnh phúc :)
n0rd 17/03/2016

Wiki cộng đồng có nghĩa là không ai sẽ đạt được (hoặc mất) danh tiếng từ việc tăng / giảm phiếu cho câu hỏi này hoặc câu trả lời của nó. Nhiều người xem các câu hỏi như thế này là cách rẻ tiền và dễ dàng để đạt được danh tiếng, vì vậy nếu bạn đánh dấu nó là wiki cộng đồng, mọi người sẽ ít có khả năng thoát khỏi hình dạng và đóng nó.
Graeme Perrow

2
"Mọi người có thể sẽ biến mọi thứ thành hình dạng và đóng nó lại": Bạn có ngụ ý rằng bạn không muốn bất kỳ nội dung hài hước / hài hước nào về chồng tràn?
Trevor Boyd Smith

2
Chỉ cần một điểm nhanh, bộ xử lý trước là một phần của ngôn ngữ và do đó không xấu / sai khi sử dụng, giống như mọi thứ khác.
Ông Boy

Câu trả lời:


410

Từ bộ nhớ, nó trông giống như thế này:

#define RETURN(result) return (result);}

int myfunction1(args) {
    int x = 0;
    // do something
    RETURN(x)

int myfunction2(args) {
    int y = 0;
    // do something
    RETURN(y)

int myfunction3(args) {
    int z = 0;
    // do something
    RETURN(z)

Đúng vậy, không có dấu ngoặc nhọn trong bất kỳ chức năng nào. Làm nổi bật cú pháp là một mớ hỗn độn, vì vậy anh ta đã sử dụng vi để chỉnh sửa (không phải vim, nó có màu cú pháp!)

Ông là một lập trình viên người Nga, người hầu hết làm việc trong ngôn ngữ lắp ráp. Anh ta cuồng tín về việc tiết kiệm càng nhiều byte càng tốt vì trước đây anh ta đã làm việc trên các hệ thống có bộ nhớ rất hạn chế. "Nó dành cho vệ tinh. Chỉ có rất ít byte, vì vậy chúng tôi sử dụng từng byte cho nhiều thứ." (bit nghịch ngợm, sử dụng lại byte hướng dẫn máy cho các giá trị số của chúng) Khi tôi cố gắng tìm hiểu các loại vệ tinh, tôi chỉ có thể nhận được "Vệ tinh quỹ đạo. Để tạo quỹ đạo."

Anh ta có hai quirks khác: Một chiếc gương lồi được gắn phía trên màn hình của anh ta "Để biết ai đang xem", và một lối thoát bất ngờ từ ghế của anh ta để thực hiện mười lần đẩy nhanh. Ông giải thích điều cuối cùng này là "Trình biên dịch tìm thấy lỗi trong mã. Đây là hình phạt".


87
"Trình biên dịch tìm thấy lỗi trong mã. Đây là hình phạt". !! Công ty tìm thấy bạn ... hình phạt cho các nhân viên đồng nghiệp!
Học

227
Ở Liên Xô, chương trình biên dịch BẠN!
Crashworks 17/03/2016

53
Khi tôi đọc về lỗi "trừng phạt" của trình biên dịch, điều đầu tiên tôi nghĩ đến là "Dulk phải ủi tay".
Graeme Perrow

124
Tôi nghĩ rằng các lập trình viên (bao gồm cả bản thân tôi) sẽ phù hợp hơn rất nhiều nếu tất cả chúng ta đã thực hiện 10 lần đẩy mỗi khi trình biên dịch tìm thấy lỗi trong mã của chúng tôi. Điều này cũng có thể làm giảm sự xuất hiện của thử nghiệm bằng cách biên dịch.
MikeyB

5
Anh chàng đó nghe thật tuyệt. Nhưng vâng, tôi không thấy cách này được cho là để cải thiện kích thước mã.
jalf

274

Điều tồi tệ nhất của tôi:

#define InterlockedIncrement(x) (x)++
#define InterlockedDecrement(x) (x)--

Tôi đã dành hai ngày trong cuộc đời để theo dõi một số vấn đề về tính năng đếm COM đa luồng vì một số kẻ ngốc đã đưa điều này vào một tệp tiêu đề. Tôi sẽ không đề cập đến công ty tôi làm việc tại thời điểm đó.

Những đạo đức của câu chuyện này? Nếu bạn không hiểu điều gì đó, hãy đọc tài liệu và tìm hiểu về nó. Đừng làm nó biến mất.


146
@Joshua: Nếu bạn chạy mã này trong một môi trường đa luồng, bạn chỉ có thể vô tình làm điều đó
1800 INFORMATION

11
"Nếu bạn không hiểu điều gì đó, hãy đọc tài liệu và tìm hiểu về nó. Đừng làm nó biến mất." - NGAY!
Paul Alexander

2
@ 1800 Thông tin: Tôi nghĩ bạn chỉ mất phiếu, đó là lý do tại sao tôi không thể cung cấp cho bạn; p
wkf

5
Hãy tha thứ cho tôi với tư cách là một lập trình viên không phải C ++: Vấn đề chính ở đây là chức năng chủ đề được chuyển đổi thành chức năng không có chủ đề? Hoặc InterlockedIncrement mong đợi một con trỏ, vì vậy bây giờ bạn sẽ tăng con trỏ thay vì những gì nó trỏ vào? Hoặc cả hai?
Tim Pietzcker

38
Vấn đề là InterlockedIncrement thường là một hàm nguyên tử được xác định trong API Windows. Vì vậy, khi mọi người gọi InterlockedIncrement, họ sẽ gọi vào một chức năng được đảm bảo để được thực thi nguyên tử. Thay vào đó, một ai đó định nghĩa một macro có cùng tên, trong đó đánh giá lại để một đồng bằng, phi nguyên tử tăng
jalf

166
#define ever (;;)
for ever { 
   ...
}

52
Tôi thích <#define mãi mãi cho (;;)> để bạn có thể viết <mãi mãi {...}>
paxdiablo 17/03/2016

một người nào đó mà tôi đã đi học bị mất điểm vì điều EVER ... anh ấy đã bị nghẹn như trong sách giáo khoa :-)
TofuBeer 17/03/2016

6
Không phải đề xuất của Pax trực tiếp từ K & R sao? Tuy nhiên, tôi không nói là nỗ lực.
Jon Ericson

Điều đó thực sự không tệ chút nào. Tôi không sử dụng for (;;)thành ngữ, nếu không tôi sẽ ngay lập tức thêm macro này vào mã của mình.
AnT

1
@hayalci: Trong emacs lisp (và một số triển khai lisp phổ biến) bạn có thể (defmacro ever ())và sau đó(require 'cl (ever))
Joe D

145
#include <iostream>
#define System S s;s
#define public
#define static
#define void int
#define main(x) main()
struct F{void println(char* s){std::cout << s << std::endl;}};
struct S{F out;};

public static void main(String[] args) {
  System.out.println("Hello World!");
}

Thách thức: Bất cứ ai cũng có thể làm điều đó với ít định nghĩa và cấu trúc hơn? ;-)


19
bạn vừa viết một trình chuyển đổi java-to-c! kinh khủng!
Andreas Petersson 17/03/2016

25
Báo cáo là "tấn công." (Tôi là đứa trẻ!)
Annika Backstrom

40
Đó là hoặc là đẹp tuyệt vời hoặc đẹp gớm ghiếc.
Chris Lutz

38
@Mark - Nó tuyên bố publicstatic as nothing, void` như int, và main(x)như main()vậy, public static void main(String[] args)biến thành int main(). Sau đó Systembiến thành S s;s, do đó System.out.println("Hello World!");biến thành S s; s.out.println("Hello World!");mà gọi printlnhàm trong Fstruct trong Sstruct.
Chris Lutz

2
Hãy xem cái này: mailcom.com/ioccc/chia/chia.c (tải xuống và biên dịch nó)
Roberto Bonvallet

130
#define private public

Tôi đã làm điều đó trước đây. Đôi khi bạn chỉ cần sửa đổi biến thành viên hoặc ghi đè hàm trong một số mã của bên thứ ba mà bạn không thể thay đổi - và họ không cung cấp trình truy cập cho bạn.
Michael Kristofik 17/03/2016

30
wow để kiểm tra đơn vị điều này thậm chí có thể hữu ích, mặc dù những bóng ma của thiết kế đối tượng sẽ ám ảnh bạn vào ban đêm.
Epaga 17/03/2016

12
Hmmm, hành vi không xác định, dễ dàng vi phạm quy tắc một định nghĩa, sự khác biệt bố cục tiềm năng. Yup, đây là một người chiến thắng.
David Thornley

10
Vì vậy, với điều đó, tôi có thể truy cập nội dung riêng tư và công cộng, nhưng không được bảo vệ và tôi không thể truy cập nội dung giữa classtừ khóa và công cụ sửa đổi truy cập đầu tiên.
Ken Bloom

3
@Ken:#define class struct #define protected public
Yakov Galka

107
#define if while

Đó là trò đùa của ai đó, nó không gây cười bởi những người bị ảnh hưởng


22
#define trong khi nếu còn sẽ quỷ quyệt hơn.
starblue 17/03/2016

7
Chúng ta nên làm rõ tuyên bố của bạn. Nó không được tìm thấy thú vị bởi những người bị ảnh hưởng . :-)
Andrew Shepherd

6
Khi tôi làm bài tập về nhà, tôi thường làm những việc này có chủ đích, chỉ để làm phiền các giáo viên của tôi.
pyon

15
Đây là một trò đùa hay nhưng nó sẽ không được biên dịch nếu có bất kỳ câu "khác" nào. Tôi đã thấy rằng #define if (x) if (true) là hiệu quả nhất.
Đồ họa Noob

32
Tôi luôn thích #define sizeof (x) rand ()
Jon

106

Kẻ gớm ghiếc:

#define begin {
#define end }
/* and so on */

Nghiêm túc mà nói, nếu bạn muốn viết mã bằng Pascal, hãy mua trình biên dịch Pascal, đừng phá hủy ngôn ngữ C đẹp.


45
Bây giờ bạn đã khiến tôi tự hỏi những ngôn ngữ nào tôi có thể mô phỏng với một tệp tiêu đề đủ thông minh.
Bill Lizard 17/03/2016

47
C không đẹp. Nó khá là xấu xí.
rlbond 17/03/2016

27
Vẻ đẹp của nó nằm ở sự đơn giản của nó. Người ta nói rằng nó có tất cả tốc độ của ngôn ngữ lắp ráp kết hợp với khả năng đọc của ... ngôn ngữ hợp ngữ :-) Tôi thích nó hơn C ++ (mặc dù tôi thích Java hơn trong công việc hàng ngày do thư viện khổng lồ của nó).
paxdiablo 17/03/2016

9
Không thực sự. Tìm nguồn gốc của Bourne cho vỏ bourne. Anh ta đã làm chính xác điều này để có được một loại hỗn độn giống ALGOL khốn.
RBerteig 17/03/2016

3
#define DO cho (int _i = 0; _i <= 1; ++ _ i) {if (_i == 1) //// LINE BREAK //// #define IF (cond); nếu (! (cond)) phá vỡ; } //// LINE BREAK //// DO printf ("a") NẾU (1 == 2);
Adrian Panasiuk

93

Một 'kiến trúc sư', một người rất khiêm tốn, bạn biết loại, có những điều sau đây:

#define retrun return

vì anh thích gõ nhanh. Bác sĩ phẫu thuật não thường thích hét vào những người thông minh hơn anh ta (điều mà khá nhiều người) và đe dọa sẽ sử dụng đai đen của anh ta cho họ.


Tôi mắc lỗi đánh máy đó rất nhiều, tôi thực sự đã xem xét nó.
Joshua

4
thay vì dạy biên tập viên của bạn để lấy lại tự động trở lại. Ive làm hackeries đó cho tôi IRC-client, ít nhất
Tetha

1
Này, tôi nghĩ tôi cũng từng làm việc với 'kiến trúc sư' đó. Cuối cùng anh ta đã được phân loại lại kiến ​​trúc sư cao cấp khi anh ta cần phải làm cho cái tôi của mình được xoa dịu.
BIBD

1
Tôi đã 'rn' được định nghĩa lại thành 'rm' trong bash, bởi vì tôi không thể gõ và trình đọc tin 'rn' mất 5 phút để khởi động và kết nối với máy chủ.
Martin Beckett

2
Bạn không thể mở một thiết bị đầu cuối mới (hoặc chuyển sang một vt khác) và làm gì killall rn?
Joe D

69

Thế giới thực? MSVC có các macro trong minmax.h, được gọi maxmin, gây ra lỗi trình biên dịch mỗi khi tôi định sử dụng std::numeric_limits<T>::max()hàm tiêu chuẩn .


2
À, vâng, đó là lý do tại sao tôi có một tiêu đề đặc biệt với sự phục hồi tinh thần # undef's sau những cái cụ thể của MS ...
Pontus Gagge 17/03/2016

3
Được giải quyết bằng (std :: num_limits <T> :: max) () Nhưng vâng, khá khó chịu.
rlbond

36
Thêm NOMINMAX vào thuộc tính dự án của bạn trong C / C ++ -> Bộ xử lý trước -> Định nghĩa tiền xử lý.
mattnewport

18
Các macro này đã tồn tại trong các tiêu đề MS dài hơn min và max đã có trong Thư viện chuẩn C ++.
Richard

4
Thậm chí còn tệ hơn khi bốn trong số các phụ thuộc bên ngoài khác của bạn cũng xác định tối thiểu / mức độ hấp dẫn khác nhau của chúng, từ các macro được phân loại kém đến các mẫu được viết tốt và một trong số chúng chỉ không thể xác định được hoặc bỏ qua những điều này ... Trong cuốn sách của tôi, ngôn ngữ là 50% để đổ lỗi.
Roman Starkov

58

Kết hợp giữa cú pháp Pascal và từ khóa tiếng Pháp:

#define debut {
#define fin }
#define si if(
#define alors ){
#define sinon }else{
#define finsi }

36
#define zut_alors thoát (-1)
MikeyB

4
Điều đó thật tuyệt vời và nó làm tôi cười thành tiếng. Vì vậy, đây về cơ bản là một phiên bản tiếng Pháp cơ bản được triển khai trong C?
Bobby

56

Raymond Chen có một câu nói rất hay chống lại việc sử dụng các macro kiểm soát dòng chảy . Ví dụ tốt nhất của anh ta là trực tiếp từ mã nguồn vỏ Bourne ban đầu:

ADDRESS alloc(nbytes)
    POS     nbytes;
{
    REG POS rbytes = round(nbytes+BYTESPERWORD,BYTESPERWORD);

    LOOP    INT     c=0;
    REG BLKPTR  p = blokp;
    REG BLKPTR  q;
    REP IF !busy(p)
        THEN    WHILE !busy(q = p->word) DO p->word = q->word OD
        IF ADR(q)-ADR(p) >= rbytes
        THEN    blokp = BLK(ADR(p)+rbytes);
            IF q > blokp
            THEN    blokp->word = p->word;
            FI
            p->word=BLK(Rcheat(blokp)|BUSY);
            return(ADR(p+1));
        FI
        FI
        q = p; p = BLK(Rcheat(p->word)&~BUSY);
    PER p>q ORF (c++)==0 DONE
    addblok(rbytes);
    POOL
}

2
Hai điểm: một, dán này làm rối tung vết lõm ban đầu. Và hai, mã có vẻ tốt cho những gì nó là: Unix C thập niên 1970 bởi một người hâm mộ cuồng nhiệt Algol-68. Nếu tại sao người cứng may mắn có thể thể hiện bản thân theo phong cách kỳ quặc, tại sao Steve Bourne không thể? Tất nhiên, ai đó đã lên án để duy trì nó, người không biết Algol 68 có thể không đánh giá cao cơ hội này để mở rộng thị hiếu của chính họ.
Darius Bacon

Tôi nghĩ rằng đây có thể là một trò đùa của Steve Bourne chứ không phải là một phong cách lập trình được đề xuất
Martin Beckett

2
Tôi đã thấy if... else... elif... ficase... esactrước đây (theo ngôn ngữ mà Bourne đã phát minh ra cho sh), nhưng loop... poollà một viên ngọc thực sự.
hobbs

54

Tôi muốn gửi cho cuộc thi một viên ngọc gọi là chaos-pp , thực hiện một ngôn ngữ chức năng bằng các macro tiền xử lý.

Một trong những ví dụ là tính toán số thứ 500 của Wikipedia hoàn toàn bởi bộ tiền xử lý:

Mã ban đầu trước khi tiền xử lý trông như thế này:

int main(void) {
   printf
     ("The 500th Fibonacci number is "
      ORDER_PP(8stringize(8to_lit(8fib(8nat(5,0,0)))))
      ".\n");
   return 0;
}

tiền xử lý tệp chúng tôi nhận được kết quả sau (sau một thời gian chờ đợi khá lâu):

$ cpp -I../inc fibonacci.c 2>/dev/null | tail
  return fib_iter(n, 0, 1);
}
# 63 "fibonacci.c"
int main(void) {
   printf
     ("The 500th Fibonacci number is "
      "139423224561697880139724382870407283950070256587697307264108962948325571622863290691557658876222521294125"
      ".\n");
   return 0;
}

1
Bạn có thể lấy mã từ CVS và xem. Tôi đã đưa một số chi tiết về nó vào blog của mình cách đây một thời gian khi tôi tình cờ thấy nó: bnpcs.blogspot.com/2009/02/. Nếu không có vấn đề với việc gỡ lỗi mã kết quả (vấn đề có dòng quá dài chúng được tạo ra bởi một "ngôn ngữ" như vậy), nó thậm chí có thể được sử dụng như một trình tạo mã thực tế cho C.
Andrew Y

Tôi chỉ có thể tưởng tượng nó sẽ mất mãi mãi để biên dịch
Paul Fultz II

52

Trực tiếp từ Qt:

#define slots   /* */
#define signals /* */

Thực sự rất tuyệt khi tương tác với các lib khác như boost :: signal ... Chỉ là một ví dụ, có nhiều người khác trong Qt tạo mã trông buồn cười như:

class X : public QObject {
   Q_OBJECT
private slots:
   //...
public signals:
   //...
};

Và đó là C ++ ... nhưng đột nhiên:

boost::signals::trackable

Không còn hợp lệ C ++ nữa.


5
:) Vì vậy, nó là một macro phá vỡ các thư viện khác không có gì. Điều đó thậm chí còn tốt hơn tôi mong đợi :)
David Rodríguez - dribeas 17/03/2016

38
Qt rất lãnh thổ và sẽ tấn công dữ dội vào các thư viện khác cố chiếm không gian tên của nó :)
Jeremy Friesner

21
Đáng buồn thay, Qt tấn công các thư viện bên ngoài không gian tên của nó bằng cách sử dụng macro
David Rodríguez - dribeas

7
May mắn là boost :: signal2 đã khắc phục vấn đề này;)
bdonlan

9
Sử dụng Q_SIGNALS và Q_SLOTS nếu bạn sợ sự tương tác này.
Tadeusz A. Kadłubowski

50

Windows.h có rất nhiều chức năng lạm dụng macro.


MrValdez cảm thấy khó chịu vì macro GetObject được tìm thấy trong Windows.h

Macro GetObject thay đổi hàm GetObject () thành GetObjectA () hoặc GetObjectW () (tùy thuộc vào việc bản dựng được biên dịch theo dạng không unicode và unicode, tương ứng)

MrValdez ghét phải làm trước dòng chức năng GetObject

#undef GetObject

Object *GetObject()

Cách khác là thay đổi tên hàm thành tên khác như GetGameObject ()


jdkoftinoff trong các bình luận đã đóng đinh nó: Vấn đề là tất cả các chức năng API của windows đều là macro.

Adam Rosenfield đã đề cập rằng các vấn đề có thể được khắc phục bằng cách xác định NOGDI, WIN32_LEAN_AND_MESE, NOMINMAX, v.v. trước khi bao gồm windows.h để xóa các vấn đề.


3
Bạn có thể loại bỏ điều này nhưng # xác định NOGDI trước khi bao gồm windows.h, tất nhiên với điều kiện là bạn không cần sử dụng bất kỳ chức năng GDI nào khác. Có một loạt các macro khác như WIN32_LEAN_AND_MESE, NOMINMAX, v.v. ngăn chặn những thứ khác không được xác định hoặc đưa vào.
Adam Rosenfield 17/03/2016

1
GetObject là một tên hàm khá chung chung. Có lẽ bạn có thể đã sử dụng một tên mô tả nhiều hơn cho bối cảnh để tránh va chạm. Tuy nhiên, đó là một trường hợp vĩ mô khá ác.
strager 17/03/2016

1
Điều khá khó chịu là win32 có tất cả các macro để chuyển đổi tên API thành FooA và FooW. Chúng tôi có vấn đề với SendMessage.
i_am_jorf 17/03/2016

6
Vấn đề là tất cả các chức năng API của windows đều là macro. Một trong số đó là tôi là GetTickCount (). Vì tôi thực hiện hầu hết các chương trình của mình bên ngoài các cửa sổ, tôi đã tìm thấy tất cả các định nghĩa trong các tiêu đề của cửa sổ và sau đó tạo tệp bao gồm của riêng tôi để xác định tất cả chúng để xác minh tính tương thích trước đó.
jdkoftinoff 17/03/2016

12
Tôi nghĩ rằng chúng tôi có một người chiến thắng. Đó là thế giới thực, đó là một ý tưởng tồi tệ đến nực cười, và nó đã ảnh hưởng đến một số lượng lớn lập trình viên vô tội. Bất cứ ai chịu trách nhiệm về viên ngọc này tại Microsoft đều phải được coi là tội phạm chiến tranh ... Điều tốt nhất là Microsoft đã không nghĩ hai lần về việc sử dụng những cái tên phổ biến đáng kinh ngạc như GetObject, SendMessage hoặc CreatWindow.
jalf

45
#define return if (std::random(1000) < 2) throw std::exception(); else return

Điều này thật là xấu xa. Đó là ngẫu nhiên, có nghĩa là nó bắn ở những nơi khác nhau mọi lúc, nó thay đổi câu lệnh return, thường có một số mã có thể tự thất bại, nó thay đổi từ khóa trông ngây thơ mà bạn sẽ không bao giờ nghi ngờ và nó sử dụng ngoại lệ từ không gian tiêu chuẩn, do đó bạn sẽ không cố gắng tìm kiếm thông qua các nguồn của mình để tìm nguồn đó. Chỉ cần rực rỡ.


4
Chỉ cần thử nghiệm cái này, ít nhất là nó không được biên dịch theo mặc định vì thiếu bao gồm ngẫu nhiên, và sau đó nó bị vặn đỏ. Tuy nhiên, nếu bạn có sự bao gồm một cách tình cờ, mọi thứ trở nên tồi tệ hơn - VC ++ 2010 đánh dấu nó vẫn là một từ khóa và không hiển thị công cụ mở rộng macro, vì vậy không có sự trợ giúp nào từ IDE để tìm thấy điều này: - /
OregonGhost

Tôi thích nó! Thiên tài thuần túy. Hãy tưởng tượng bạn có thể trông tốt như thế nào khi bạn "Gỡ lỗi" Ứng dụng này khi không có ai khác quản lý.
brice

36

Một đồng nghiệp và tôi đã tìm thấy hai viên đá quý này trong một số mã của chúng tôi để truyền phát đối tượng. Các macro này đã được khởi tạo trong MỌI THỨ tệp lớp đã phát trực tuyến. Không chỉ mã này gớm ghiếc trên khắp cơ sở mã của chúng tôi, khi chúng tôi tiếp cận tác giả ban đầu về nó, anh ấy đã viết một bài viết 7 trang trên wiki nội bộ của chúng tôi để bảo vệ điều này như là cách duy nhất có thể để thực hiện những gì anh ấy đang cố gắng làm ở đây.

Không cần phải nói, nó đã được tái cấu trúc và không còn được sử dụng trong cơ sở mã của chúng tôi.

Đừng bỏ qua các từ khóa được tô sáng. Đây là TẤT CẢ vĩ mô

#define DECLARE_MODIFICATION_REQUEST_PACKET( T )                                                \
namespace NameSpace                                                                     \
{                                                                                       \
                                                                                        \
class T##ElementModificationRequestPacket;                                                          \
}                                                                                       \
                                                                                        \
DECLARE_STREAMING_TEMPLATES( IMPEXP_COMMON_TEMPLATE_DECLARE, NameSpace::ElementModificationRequestPacket<T>, OtherNameSpace::NetPacketBase )    \
DLLIMPEXP_COMMON_TEMPLATE_DECLARE( NameSpace::ElementModificationRequestPacket<T> )     \
DECLARE_AUTOGENERATION_TEMPLATES( DLLIMPEXP_COMMON_TEMPLATE_DECLARE, NameSpace::T##ModificationRequestPacket, NameSpace::ElementModificationRequestPacket<T> )      \
                                                                                        \
namespace NameSpace {                                                                   \
class DLLIMPEXP_COMMON T##ModificationRequestPacket : public ElementModificationRequestPacket<T>\
{                                                                                       \
public:                                                                                 \
    T##ModificationRequestPacket( NetBase * pParent )                                   \
    : ElementModificationRequestPacket<T>( pParent ), m_Gen() {}                            \
                                                                                        \
    T##ModificationRequestPacket( NetBase * pParent,                                    \
                            Action          eAction,                                    \
                            const T &   rT )                                            \
    : ElementModificationRequestPacket<T>( pParent, eAction, rT ), m_Gen() {}               \
                                                                                        \
    T##ModificationRequestPacket( const T##ModificationRequestPacket & rhs )                        \
    : ElementModificationRequestPacket<T>( rhs ), m_Gen() {}                                \
                                                                                        \
    virtual                     ~T##ModificationRequestPacket( void ) {}                        \
                                                                                        \
    virtual Uint32          GetPacketTypeID( void ) const                           \
    {                                                                                   \
        return Net::T##_Modification_REQUEST_PACKET;                                        \
    }                                                                                   \
                                                                                        \
    virtual OtherNameSpace::ClassID GetClassID ( void ) const                           \
    {                                                                                   \
        return OtherNameSpace::NetBase::GenerateHeader( OtherNameSpace::ID__LICENSING,  \
                                                         Net::T##_Modification_REQUEST_PACKET );    \
    }                                                                                   \
                                                                                        \
    virtual T##ModificationRequestPacket * Create( void ) const                             \
    { return new T##ModificationRequestPacket( m_pParent ); }                                   \
                                                                                        \
    T##ModificationRequestPacket() {}                                                           \
                                                                                        \
protected:                                                                              \
    OtherNameSpace::ObjectAutogeneration<T##ModificationRequestPacket> m_Gen;                       \
                                                                                        \
    friend class OtherNameSpace::StreamingBase::StreamingClassInfoT<T##ModificationRequestPacket >;                     \
    OtherNameSpace::StreamingBase::Streaming<T##ModificationRequestPacket, ElementModificationRequestPacket<T> >    m_Stream;   \
                                                                                        \
};                                                                                      \
}                                                                                       \
DLLIMPEXP_COMMON_TEMPLATE_DECLARE( ThirdNameSpace::ListenerBase<const NameSpace::T##ModificationRequestPacket> )            \
DLLIMPEXP_COMMON_TEMPLATE_DECLARE( ThirdNameSpace::BroadcasterT<const NameSpace::T##ModificationRequestPacket> )            \
typedef  ThirdNameSpace::BroadcasterT<const T##ModificationRequestPacket>  T##ModifiedBroadcaster;



#define IMPLEMENT_MODIFICATION_REQUEST_PACKET( T )                                                                  \
DLLIMPEXP_COMMON_TEMPLATE_INSTANTIATE( NameSpace::ElementModificationRequestPacket<T> )                         \
DLLIMPEXP_COMMON_TEMPLATE_INSTANTIATE( ThirdNameSpace::ListenerBase<const NameSpace::T##ModificationRequestPacket> )        \
DLLIMPEXP_COMMON_TEMPLATE_INSTANTIATE( ThirdNameSpace::BroadcasterT<const NameSpace::T##ModificationRequestPacket> )        \
INSTANTIATE_STREAMING_TEMPLATES( DLLIMPEXP_COMMON_TEMPLATE_INSTANTIATE, NameSpace::ElementModificationRequestPacket<T>, OtherNameSpace::NetPacketBase ) \
INSTANTIATE_AUTOGENERATION_TEMPLATES( DLLIMPEXP_COMMON_TEMPLATE_INSTANTIATE, NameSpace::T##ModificationRequestPacket, NameSpace::ElementModificationRequestPacket<T> )

Cập nhật (ngày 17 tháng 12 năm 2009):

Thêm tin tốt về tác giả vĩ mô gớm ghiếc này. Kể từ tháng 8, nhân viên chịu trách nhiệm cho sự quái dị này đã bị sa thải.


3
Ông rõ ràng chưa bao giờ nghe nói: "Gỡ lỗi khó gấp đôi so với viết mã ngay từ đầu. Do đó, nếu bạn viết mã càng khéo léo càng tốt, theo định nghĩa, bạn không đủ thông minh để gỡ lỗi." -Brian W. Kernighan
Trevor Boyd Smith

33

Tôi đã làm như sau, và tôi nghĩ rằng tôi đã học được điều gì đó từ nó.

Vào năm 1992, tôi đã viết một thông dịch viên Lisp nhỏ. Nó không được thực hiện trong C bình thường, nhưng trong một ngôn ngữ giống như C được giải thích. Ngôn ngữ giống như C này đã sử dụng bộ xử lý trước C tiêu chuẩn.

Các Lisp thông dịch dĩ nhiên chứa các chức năng xe , được sử dụng trong Lisp để trả lại phần tử đầu tiên trong danh sách, và cdr , mà trả về phần còn lại của danh sách. Chúng được thực hiện như thế này:

LISPID car(LISPID id) {
    CHECK_CONS("car", 1, id);
    return cons_cars[id - CONS_OFFSET];
} /* car */

LISPID cdr(LISPID id) {
    CHECK_CONS("cdr", 1, id);
    return cons_cdrs[id - CONS_OFFSET];
} /* cdr */

(Dữ liệu được lưu trữ trong các mảng, vì không có cấu trúc nào. Cons_OFFSET là hằng số 1000.)

carcdr được sử dụng thường xuyên trong Lisp và ngắn, và vì các lệnh gọi hàm không nhanh lắm trong ngôn ngữ thực hiện, tôi đã tối ưu hóa mã của mình bằng cách triển khai hai hàm Lisp đó dưới dạng macro:

#define car(id) (CHECK_CONS("car", 1, (id)), cons_cars[(id) - CONS_OFFSET])
#define cdr(id) (CHECK_CONS("car", 1, (id)), cons_cdrs[(id) - CONS_OFFSET])

CHECK_CONS kiểm tra xem đối số của nó thực sự là một danh sách và vì nó cũng được sử dụng thường xuyên trong trình thông dịch và rất ngắn, tôi đã viết rằng đó cũng là một đối tượng như một macro:

#define CHECK_CONS(fun, pos, arg)   \
    (!IS_CONS(arg) ?        \
        LISP_ERROR("Arg " + pos + " to " + fun +    \
                   " must be a list: " + lispid2string(arg)) : 0)

IS_CONSLISP_ERROR cũng được sử dụng thường xuyên, vì vậy tôi cũng biến chúng thành macro:

#define IS_CONS(id) \
    (   intp(id) && (id) >= CONS_OFFSET     \
     && ((id) - CONS_OFFSET) < sizeof(cons_cars))

#define LISP_ERROR(str)     (throw((str) + "\n"))

Có vẻ hợp lý?

Nhưng sau đó, tại sao toàn bộ hệ thống gặp sự cố trên dòng này:

id2 = car(car(car(car((id1))));

Tôi đã làm việc một thời gian dài để tìm ra vấn đề, cho đến khi cuối cùng tôi đã kiểm tra xem dòng ngắn đó đã được mở rộng bởi bộ xử lý trước. Nó đã được mở rộng thành một dòng gồm 31370 ký tự mà tôi đã chia ở đây thành các dòng (502 trong số chúng) để rõ ràng:

id2 = ((!(intp( (((!(intp( (((!(intp( (((!(intp( (id1)) && (
(id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (id1))) + "\n")) : 0), cons_cars[(id1) - 1000])))
&& ( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp( (id1)) && (
(id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (id1))) + "\n")) : 0), cons_cars[(id1) - 1000]))) -
1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" +
" must be a list: " + lispid2string( (((!(intp( (id1)) && ( (id1))
>= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg "
+ 1 + " to " + "car" + " must be a list: " + lispid2string(
(id1))) + "\n")) : 0), cons_cars[(id1) - 1000])))) + "\n")) : 0),
cons_cars[(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) -
1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" +
" must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) && ( (((!(intp( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) >= 1000 && (( (((!(intp(
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) - 1000) < sizeof(cons_cars))
? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 &&
(( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to
" + "car" + " must be a list: " + lispid2string( (id1))) + "\n"))
: 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && (
(id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (id1))) + "\n")) : 0), cons_cars[(id1) - 1000])))
>= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) -
1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" +
" must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000])))) + "\n")) : 0),
cons_cars[(((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && ((
(id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to "
+ "car" + " must be a list: " + lispid2string( (id1))) + "\n")) :
0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1))
>= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg "
+ 1 + " to " + "car" + " must be a list: " + lispid2string(
(id1))) + "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && ((
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000])) - 1000]))) && ( (((!(intp(
(((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) -
1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" +
" must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) && ( (((!(intp( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) >= 1000 && (( (((!(intp(
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) - 1000) < sizeof(cons_cars))
? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 &&
(( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to
" + "car" + " must be a list: " + lispid2string( (id1))) + "\n"))
: 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && (
(id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (id1))) + "\n")) : 0), cons_cars[(id1) - 1000])))
>= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) -
1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" +
" must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000])))) + "\n")) : 0),
cons_cars[(((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && ((
(id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to "
+ "car" + " must be a list: " + lispid2string( (id1))) + "\n")) :
0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1))
>= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg "
+ 1 + " to " + "car" + " must be a list: " + lispid2string(
(id1))) + "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && ((
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000])) - 1000]))) >= 1000 && ((
(((!(intp( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && ((
(id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to "
+ "car" + " must be a list: " + lispid2string( (id1))) + "\n")) :
0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1))
>= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg "
+ 1 + " to " + "car" + " must be a list: " + lispid2string(
(id1))) + "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && ((
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) && ( (((!(intp( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) >= 1000 && (( (((!(intp(
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) - 1000) < sizeof(cons_cars))
? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 &&
(( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to
" + "car" + " must be a list: " + lispid2string( (id1))) + "\n"))
: 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && (
(id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (id1))) + "\n")) : 0), cons_cars[(id1) - 1000])))
>= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) -
1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" +
" must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000])))) + "\n")) : 0),
cons_cars[(((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && ((
(id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to "
+ "car" + " must be a list: " + lispid2string( (id1))) + "\n")) :
0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1))
>= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg "
+ 1 + " to " + "car" + " must be a list: " + lispid2string(
(id1))) + "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && ((
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000])) - 1000]))) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (((!(intp( (((!(intp( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) && ( (((!(intp( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) >= 1000 && (( (((!(intp(
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) - 1000) < sizeof(cons_cars))
? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 &&
(( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to
" + "car" + " must be a list: " + lispid2string( (id1))) + "\n"))
: 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && (
(id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (id1))) + "\n")) : 0), cons_cars[(id1) - 1000])))
>= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) -
1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" +
" must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000])))) + "\n")) : 0),
cons_cars[(((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && ((
(id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to "
+ "car" + " must be a list: " + lispid2string( (id1))) + "\n")) :
0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1))
>= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg "
+ 1 + " to " + "car" + " must be a list: " + lispid2string(
(id1))) + "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && ((
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000])) - 1000])))) + "\n")) : 0),
cons_cars[(((!(intp( (((!(intp( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1))
&& ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (id1))) + "\n")) : 0), cons_cars[(id1) - 1000])))
>= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) -
1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" +
" must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars))

18
I optimized my code by implementing those [..] functions as macros- những lời cuối cùng nổi tiếng ...
BlueRaja - Daniel Pflughoeft

3
Tôi đã vi phạm tương tự trong các phiên bản đầu của trình thông dịch Postcript của tôi. Đẩy và bật là các chức năng quan trọng đến mức chúng phải là macro . Nhưng việc soạn một biểu thức liên quan đến nhiều hơn một trong những điều này dẫn đến hành vi không xác định. Hành vi không xác định chỉ bị bắt khi biên dịch ở -O3. Và tại -O3, các phiên bản chức năng dù sao cũng đã được nội tuyến.
luser droog

29

Tôi đã từng phải chuyển một ứng dụng C từ unix sang windows, bản chất cụ thể của nó sẽ vẫn chưa được đặt tên để bảo vệ người có tội. Người viết nó là một giáo sư không quen viết mã sản xuất, và rõ ràng đã đến C từ một số ngôn ngữ khác. Nó cũng xảy ra rằng tiếng Anh không phải là ngôn ngữ đầu tiên của anh ấy, mặc dù đất nước anh ấy đến từ phần lớn mọi người nói nó khá tốt.

Ứng dụng của anh ta đã sử dụng rất nhiều bộ tiền xử lý để biến ngôn ngữ C thành định dạng mà anh ta có thể hiểu rõ hơn. Nhưng các macro anh sử dụng nhiều nhất được xác định trong tệp tiêu đề có tên 'Thing.h' (nghiêm túc), bao gồm các mục sau:

#define I  Any void_me
#define thou  Any void_thee
#define iam(klas)  klas me = (klas) void_me
#define thouart(klas)  klas thee = (klas) void_thee
#define my  me ->
#define thy  thee ->
#define his  him ->
#define our  my methods ->
#define your  thy methods ->

... mà sau đó ông đã sử dụng để viết những điều quái dị như sau:

void Thing_setName (I, const char *name) {
iam (Thing);
if (name != my name) {
    Melder_free (my name);
    my name = Melder_wcsdup (name);
    }
    our nameChanged (me);
}

void Thing_overrideClass (I, void *klas) {
iam (Thing);
my methods = (Thing_Table)klas;
if (! ((Thing_Table) klas) -> destroy)
    ((Thing_Table) klas) -> _initialize (klas);
}

Toàn bộ dự án (~ 60.000 LỘC) được viết theo phong cách tương tự - địa ngục marco, tên lạ, biệt ngữ Olde-English, v.v. May mắn thay, chúng tôi đã có thể ném mã ra từ khi tôi tìm thấy một thư viện OSS thực hiện cùng một thuật toán hàng chục của thời gian nhanh hơn.

(Tôi đã sao chép và chỉnh sửa câu trả lời này mà ban đầu tôi đã thực hiện cho câu hỏi này ).


3
Tôi khá bị thu hút bởi những người sở hữu và tiếng Anh cổ xưa, vì tất cả những điều đó tất nhiên tôi đồng ý mã trông rất tệ.
Darius Bacon

27

Điều tồi tệ nhất tôi từng gặp là trong một sản phẩm chứa một bộ thực thi mà nhà lãnh đạo kỹ thuật được chỉ định đã không tìm ra các thư viện.

Thay vào đó, anh ta có các bộ tệp được chia sẻ trong một số thư mục Visual Source Safe. Sau đó, ông nhận ra rằng họ cần phải cư xử hơi khác nhau cho mỗi ứng dụng.

Có một số bước tái cấu trúc bạn có thể áp dụng ở đây.

Thay vào đó, anh ấy đã sử dụng #ifdefs

   void DisplayLoadError()
   {
   #if defined __TIMETABLE_EDITOR
   MessageBox("Timetable Editor failed to load the correct timetable", MB_ERROR);
   #else if defined __SCHEDULESET_EDITOR
   MessageBox("Schedule Set Editor faied to load the correct Schedule Set", MB_ERROR);
   #else if defined __ROSTER_EDITOR
   MessageBox("Roster Editor failed to load the correct Roster", MB_ERROR);
   #endif
   }

17

Việc sử dụng bộ tiền xử lý LINE để tạo ID duy nhất cho các tin nhắn được truyền qua mạng:

NetworkMessages.h

#define MSG_LOGIN  __LINE__
#define MSG_LOGOUT __LINE__
#define MSG_CHAT   __LINE__

Đây là một ví dụ trong đó macro thực sự tốt hơn giải pháp phi vĩ mô:

Trong một lớp giải pháp phi vĩ mô, các hàm và biến phải được xây dựng để theo dõi thông điệp ID là gì. Nhà phát triển có thể hoặc không thể làm cho việc theo dõi ID tin nhắn trở nên phức tạp trong khi điều này dễ đọc và gỡ lỗi hơn.

Ngoài ra, việc thêm tin nhắn mới chỉ dễ dàng hơn bằng cách thêm tin nhắn vào nguồn.

Nhược điểm của tình huống này là tệp phải được bao gồm trong tất cả các mã sử dụng tin nhắn. Thời gian biên dịch sẽ tăng lên bất cứ khi nào một tin nhắn được chỉnh sửa.


8
Và các phiên bản có thể không tương thích với nhau (không tốt!). Làm thế nào mà một enum không đủ?
strager 17/03/2016

Cả cái này và Enum đều có cùng một vấn đề không tương thích.
MrValdez 17/03/2016

17
Bây giờ tôi đi cùng và sắp xếp #defines ... và giao thức thay đổi. Hoặc tôi nhận được tôn giáo Doxygen và ghi lại tất cả các mã thông báo và giao thức thay đổi. Ít nhất một enum ổn định dưới sự thay đổi sau này.
RBerteig 17/03/2016

3
@MrValdez, việc giữ một khối enum theo thứ tự ít hạn chế hơn so với việc giữ các định nghĩa trên cùng một dòng liên quan đến bắt đầu tập tin.
peterchen

Tôi biết rằng đây là một bài viết cũ, nhưng nó thậm chí còn hoạt động? Ý tôi là #define sẽ chỉ thay thế các hằng số thông báo thành LINE và chỉ sau đó LINE sẽ được mở rộng thành số dòng, vì vậy mỗi lần chúng ta sử dụng cùng một hằng số trên các dòng khác nhau - nó sẽ thay đổi (thành số dòng hiện tại)?
XzKto

16

Một ví dụ khá tệ:

#ifdef __cplusplus
#define class _vclass
#endif

Điều này cho phép cấu trúc C chứa biến thành viên được gọi là classtrình biên dịch C ++. Có hai tiêu đề với cấu trúc này trong đó; một trong số chúng cũng chứa 'lớp #undef' ở cuối và lớp kia thì không.


1
Đây là lý do tại sao Objective-C sử dụng @classthay vì class.

14

Trong một năm của Cuộc thi mã hóa C bị xáo trộn quốc tế, có một mục trong đó toàn bộ chương trình là:

P

Với điều kiện bạn có thể định nghĩa P trong tệp thực hiện là bất kỳ chương trình nào bạn muốn.

Như tôi nhớ lại, nó đã chiến thắng ở một trong các hạng mục, và năm sau, một quy tắc đã xuất hiện không đồng ý với phong cách nhập cảnh đó.

(Chỉnh sửa: sáu tháng sau hoặc một cái gì đó ... Tôi chắc chắn rằng điều "Không IOCCC" không nằm trong câu hỏi chính khi tôi viết bài này ...)


12

Một ngày nọ, tôi cảm thấy buồn chán và chơi xung quanh với các khối trong Objective-C ...

#define Lambda(var, body) [^ id(id (var)) { return (body);} copy]
#define Call(f, arg) ((id(^)(id))(f))(arg)
#define Int(num) [NSNumber numberWithInteger:(num)]
#define Mult(a, b) Int([(a) integerValue] * [(b) integerValue])
#define Add(a, b) Int([(a) integerValue] + [(b) integerValue])
#define Sub1(n) Int([(n) integerValue] - 1)
#define Add1(n) Int([(n) integerValue] + 1)
#define If(cond, thenblock, elseblock) ([(cond) integerValue] ? (thenblock) : (elseblock))
#define Cons(car, cdr_) [[ConsType alloc] initWithCar:(car) cdr:(cdr_)]
#define Car(list) [(list) car]
#define Cdr(list) [(list) cdr]
#define Define(var, value) id var = (value)
#define Nullq(value) Int(value == nil)

cho phép những thứ "thú vị" như:

Define(Y, Lambda(f, Call(Lambda(x, Call(x, x)),
                         Lambda(x, Call(f, Lambda(y, Call(Call(x, x), y)))))));
Define(AlmostTotal, Lambda(f, Lambda(list, If(Nullq(list), Int(0),
                                              Add(Car(list), Call(f, Cdr(list)))))));
Define(Total, Call(Y, AlmostTotal));
Print(Call(Total, Cons(Int(4), Cons(Int(5), Cons(Int(8), nil)))));

(một số định nghĩa hàm và lớp không được hiển thị vì lý do ngắn gọn)


"Tôi đã chán một ngày" nhà phát triển nổi tiếng cuối cùng :)
Richard J. Ross III

11

Điều tồi tệ nhất tôi thấy là việc không sử dụng :-)

Ai đó đã viết một hàm strcpy (tôi nghĩ rằng đó là ... hơn 10 năm trước) hoạt động bên trong một phương thức (vì họ không muốn chi phí gọi strcpy ... thở dài).

Họ nói rằng nó sẽ không hoạt động đối với các ký tự tiếng Nhật nên họ đã thêm "nếu" khi bắt đầu làm ASCII hoặc Unicode. Vào thời điểm đó, đoạn mã dài khoảng một màn hình ... có khả năng giết chết sự kết hợp bộ nhớ cache và xóa các khoản tiết kiệm được cho là của anh ta để nội tuyến mã.

Mã này được lưu giống hệt nhau cho các loại (vì vậy nên đã sử dụng một macro).

Tất nhiên, strcpy mà họ viết chậm hơn nhiều so với trình biên dịch được điều chỉnh bằng tay trong thư viện chuẩn ...

Tất nhiên, nếu họ vừa mới thực hiện tất cả như một macro, nó có thể đã được thay thế bằng một lời kêu gọi ...

Tất nhiên tôi rời công ty (không trực tiếp vì điều đó ...)


The code was identical save for the types (so should have used a macro).Không, anh ta nên sử dụng một mẫu.
BlueRaja - Daniel Pflughoeft

1
Anh ta nên sử dụng strcpy! (và đó là mã C không phải C ++ nên không có mẫu) :-P
TofuBeer

Tối ưu hóa sớm là gốc rễ của mọi tội lỗi.
Hubert Kario

11

Bắt buộc

#define FOR  for

#define ONE  1
#define TWO  2
...

Ai biết?


5
Nhưng - nhưng - nhưng KHÔNG CÓ BÀI VIẾT TRONG MÃ! ;)
Bernard

họ vẫn là mon, nên đặt tên theo mục đích / ý định không thay thế biểu tượng. Mã COBOL Tôi đã nghe nói về họ đã tạo biến 5 = 5 và sau đó có mã nói rằng tập 5 = 10 ... những người thực sự ngạc nhiên khi họ làm var + 5 và nhận var + 10.
Greg Domjan

1
Chưa bao giờ nghe nói về điều đó với COBOL, chỉ với FORTRAN. Tất nhiên, COBOL có ZERO, ZEROS và ZEROES là những từ dành riêng, tất cả đều có nghĩa chính xác giống như 0.
David Thornley

Tốt hơn nhiều so với "#define ONE 0". Nếu bạn muốn cười khúc khích, hãy tìm kiếm trên web và ngạc nhiên với số lần truy cập khác không.
reuben

11
#define TRUE 0 // dumbass

Người đã làm điều này tự giải thích vài năm sau đó - hầu hết (nếu không phải tất cả) các hàm thư viện C trả về 0 như một dấu hiệu cho thấy mọi thứ đều ổn. Vì vậy, anh muốn có thể viết mã như:

if (memcpy(buffer, packet, BUFFER_SIZE) == TRUE) {
; // rape that packet
}

Không cần phải nói, không ai trong nhóm của chúng tôi (người thử nghiệm hoặc nhà phát triển) từng dám liếc nhìn mã của anh ta một lần nữa.


1
tôi đổ lỗi cho các chức năng thư viện C đã tạo ra 0 "mọi thứ đều ổn": P
RCIX

6
Tại sao không tuyên bố một cái gì đó như thế #define FLAG_SUCCESS 0nào?
pyon

11

Tôi duy trì mã có gotos trong macro. Vì vậy, một hàm sẽ có nhãn ở cuối nhưng không có goto hiển thị trong mã chức năng. Để làm cho vấn đề tồi tệ hơn, macro nằm ở cuối các câu lệnh khác thường tắt khỏi màn hình trừ khi bạn cuộn theo chiều ngang.

#define CHECK_ERROR if (!SomeCondition) goto Cleanup

void SomeFunction() 
{ 
    SomeLongFunctionName(ParamOne, ParamTwo, ParamThree, ParamFour); CHECK_ERROR  
    //SomeOtherCode  
    Cleanup:    
   //Cleanup code  
}

Điều tồi tệ hơn là khi các macro ẩn cả các gotocâu lệnh cũng như các định nghĩa của nhãn đích. Hoàn toàn kỳ diệu.
thiệu lại

Tôi đã chịu đựng điều đó - nhưng các macro trông giống như các cuộc gọi chức năng.
Jonathan Leffler

10
#include <iostream>
#define public_static_void_main(x) int main()
#define System_out_println(x) std::cout << x << std::endl

public_static_void_main(String[] args) {
  System_out_println("Hello World!");
}

3
Và BẠN muốn viết một thời gian chạy. Hãy nhìn xem tôi đã tiết kiệm được bao nhiêu thời gian!
Bernard

4
@Trevor: Vâng ... những người thông minh vẫn đang làm Java thay thế. chạy để bảo vệ
Michael Myers

Nếu bạn đặt [] sau args thay vì trước và "#define String int argc, char *", nó sẽ biên dịch (thật đáng buồn).
Adam Rosenfield 17/03/2016

16
Tôi thích cái khác tốt hơn. Cái này cho thấy một cái gì đó gần với Java được viết bằng một vài macro. Một cái khác cho thấy Java chính xác được viết với rất nhiều macro và cấu trúc lén lút với các thành viên hàm. Trò thứ nhất là một trò đùa rẻ tiền, trong khi trò thứ hai là một trò đùa công phu và tốt đẹp.
Chris Lutz

10

Bởi một người bạn cùng lớp không hiểu các quy tắc về số ma thuật:
#define TWO_HUNDRED_AND_EIGHTY_THREE_POINT_ONE 283.1


9

ASA - http://www.ingber.com/#ASA

Bạn thực sự phải tải về nó để đánh giá cao nó. Toàn bộ dòng công việc được xác định bởi các macro. Nó hoàn toàn không thể đọc được. Ví dụ -

 if (asa_open == FALSE) {
asa_open = TRUE;
++number_asa_open;
#if ASA_PRINT
if (number_asa_open == 1) {
  /* open the output file */
#if USER_ASA_OUT
  if (!strcmp (OPTIONS->Asa_Out_File, "STDOUT")) {
#if INCL_STDOUT
    ptr_asa_out = stdout;
#endif /* INCL_STDOUT */
  } else {
#if ASA_SAVE
    ptr_asa_out = fopen (OPTIONS->Asa_Out_File, "a");
#else
    ptr_asa_out = fopen (OPTIONS->Asa_Out_File, "w");
#endif
  }
#else /* USER_ASA_OUT */
  if (!strcmp (ASA_OUT, "STDOUT")) {
#if INCL_STDOUT
    ptr_asa_out = stdout;
#endif /* INCL_STDOUT */
  } else {
#if ASA_SAVE
    ptr_asa_out = fopen (ASA_OUT, "a");
#else
    ptr_asa_out = fopen (ASA_OUT, "w");
#endif
  }
#endif /* USER_ASA_OUT */
} else {
#if USER_ASA_OUT
  if (!strcmp (OPTIONS->Asa_Out_File, "STDOUT")) {
#if INCL_STDOUT
    ptr_asa_out = stdout;
#endif /* INCL_STDOUT */
  } else {
    ptr_asa_out = fopen (OPTIONS->Asa_Out_File, "a");
  }
#else
  if (!strcmp (ASA_OUT, "STDOUT")) {
#if INCL_STDOUT
    ptr_asa_out = stdout;
#endif /* INCL_STDOUT */
  } else {
    ptr_asa_out = fopen (ASA_OUT, "a");
  }
#endif
  fprintf (ptr_asa_out, "\n\n\t\t number_asa_open = %d\n",
           number_asa_open);
}
#endif /* ASA_PRINT */
} else {
++recursive_asa_open;
#if ASA_PRINT
if (recursive_asa_open == 1) {
  /* open the output file */
#if ASA_SAVE
#if USER_ASA_OUT
  if (!strcmp (OPTIONS->Asa_Out_File, "STDOUT")) {
#if INCL_STDOUT
    ptr_asa_out = stdout;
#endif /* INCL_STDOUT */
  } else {
    ptr_asa_out = fopen (OPTIONS->Asa_Out_File, "a");
  }
#else
  if (!strcmp (ASA_OUT, "STDOUT")) {
#if INCL_STDOUT
    ptr_asa_out = stdout;
#endif /* INCL_STDOUT */
  } else {
    ptr_asa_out = fopen (ASA_OUT, "a");
  }
#endif
#else /* ASA_SAVE */
#if USER_ASA_OUT
  if (!strcmp (OPTIONS->Asa_Out_File, "STDOUT")) {
#if INCL_STDOUT
    ptr_asa_out = stdout;
#endif /* INCL_STDOUT */
  } else {

Vân vân.

Và đó chỉ là thiết lập các tùy chọn. toàn bộ chương trình là như thế.


2
Ôi chúa ơi ... tôi nghĩ mình đang bị chóng mặt.
Michael Foukarakis
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.