2010-08-22 35 views
12

Đối với một số cơ sở. Cơ sở 1 thậm chí. Một số loại thay thế phức tạp.Tôi có thể thêm số bằng bộ tiền xử lý C/C++ không?

Ngoài ra, và tất nhiên, làm điều này không phải là một ý tưởng hay trong mã sản xuất thực tế. Tôi chỉ hỏi tò mò.

+24

Bạn sẽ không thể đại diện cho nhiều số trong cơ sở 1. – Artefacto

+3

Chúng ta không bao giờ nên để lại Base 1. bit là điều ác. –

+0

Cơ sở 1 bổ sung rất dễ dàng! Chỉ cần ghép các đối số macro/macro. – alternative

Trả lời

10

Bạn có thể viết macro tương đối dễ dàng, thêm hai số nguyên trong nhị phân. Ví dụ: macro tổng hợp hai số nguyên 4 bit theo dạng nhị phân:

#include "stdio.h" 

// XOR truth table 
#define XOR_0_0 0 
#define XOR_0_1 1 
#define XOR_1_0 1 
#define XOR_1_1 0 

// OR truth table 
#define OR_0_0 0 
#define OR_0_1 1 
#define OR_1_0 1 
#define OR_1_1 1 

// AND truth table 
#define AND_0_0 0 
#define AND_0_1 0 
#define AND_1_0 0 
#define AND_1_1 1 

// concatenation macros 
#define XOR_X(x,y) XOR_##x##_##y 
#define OR_X(x,y) OR_##x##_##y 
#define AND_X(x,y) AND_##x##_##y 
#define OVERFLOW_X(rc1,rc2,rc3,rc4, rb1,rb2,rb3,rb4, a1,a2,a3,a4, b1,b2,b3,b4) OVERFLOW_##rc1 (rc1,rc2,rc3,rc4, rb1,rb2,rb3,rb4, a1,a2,a3,a4, b1,b2,b3,b4) 

// stringification macros 
#define STR_X(x) #x 
#define STR(x) STR_X(x) 

// boolean operators 
#define XOR(x,y) XOR_X(x,y) 
#define OR(x,y) OR_X(x,y) 
#define AND(x,y) AND_X(x,y) 

// carry_bit + bit1 + bit2 
#define BIT_SUM(carry,bit1,bit2) XOR(carry, XOR(bit1,bit2)) 
// carry_bit + carry_bit_of(bit1 + bit2) 
#define CARRY_SUM(carry,bit1,bit2) OR(carry, AND(bit1,bit2)) 

// do we have overflow or maybe result perfectly fits into 4 bits ? 
#define OVERFLOW_0(rc1,rc2,rc3,rc4, rb1,rb2,rb3,rb4, a1,a2,a3,a4, b1,b2,b3,b4) SHOW_RESULT(rc1,rc2,rc3,rc4, rb1,rb2,rb3,rb4, a1,a2,a3,a4, b1,b2,b3,b4) 
#define OVERFLOW_1(rc1,rc2,rc3,rc4, rb1,rb2,rb3,rb4, a1,a2,a3,a4, b1,b2,b3,b4) SHOW_OVERFLOW(rc1,rc2,rc3,rc4, rb1,rb2,rb3,rb4, a1,a2,a3,a4, b1,b2,b3,b4) 

// draft-horse macros which performs addition of two 4-bit integers 
#define ADD_BIN_NUM(a1,a2,a3,a4, b1,b2,b3,b4) ADD_BIN_NUM_4(0,0,0,0, 0,0,0,0, a1,a2,a3,a4, b1,b2,b3,b4) 
#define ADD_BIN_NUM_4(rc1,rc2,rc3,rc4, rb1,rb2,rb3,rb4, a1,a2,a3,a4, b1,b2,b3,b4) ADD_BIN_NUM_3(rc1,rc2,rc3,AND(CARRY_SUM(0,a4,b4),OR(a4,b4)), rb1,rb2,rb3,BIT_SUM(0,a4,b4), a1,a2,a3,a4, b1,b2,b3,b4) 
#define ADD_BIN_NUM_3(rc1,rc2,rc3,rc4, rb1,rb2,rb3,rb4, a1,a2,a3,a4, b1,b2,b3,b4) ADD_BIN_NUM_2(rc1,rc2,AND(CARRY_SUM(rc4,a3,b3),OR(a3,b3)),rc4, rb1,rb2,BIT_SUM(rc4,a3,b3),rb4, a1,a2,a3,a4, b1,b2,b3,b4) 
#define ADD_BIN_NUM_2(rc1,rc2,rc3,rc4, rb1,rb2,rb3,rb4, a1,a2,a3,a4, b1,b2,b3,b4) ADD_BIN_NUM_1(rc1,AND(CARRY_SUM(rc3,a2,b2),OR(a2,b2)),rc3,rc4, rb1,BIT_SUM(rc3,a2,b2),rb3,rb4, a1,a2,a3,a4, b1,b2,b3,b4) 
#define ADD_BIN_NUM_1(rc1,rc2,rc3,rc4, rb1,rb2,rb3,rb4, a1,a2,a3,a4, b1,b2,b3,b4)  OVERFLOW(AND(CARRY_SUM(rc2,a1,b1),OR(a1,b1)),rc2,rc3,rc4, BIT_SUM(rc2,a1,b1),rb2,rb3,rb4, a1,a2,a3,a4, b1,b2,b3,b4) 
#define OVERFLOW(rc1,rc2,rc3,rc4, rb1,rb2,rb3,rb4, a1,a2,a3,a4, b1,b2,b3,b4) OVERFLOW_X(rc1,rc2,rc3,rc4, rb1,rb2,rb3,rb4, a1,a2,a3,a4, b1,b2,b3,b4) 
#define SHOW_RESULT(rc1,rc2,rc3,rc4, rb1,rb2,rb3,rb4, a1,a2,a3,a4, b1,b2,b3,b4) STR(a1) STR(a2) STR(a3) STR(a4) " + " STR(b1) STR(b2) STR(b3) STR(b4) " = " STR(rb1) STR(rb2) STR(rb3) STR(rb4) 
#define SHOW_OVERFLOW(rc1,rc2,rc3,rc4, rb1,rb2,rb3,rb4, a1,a2,a3,a4, b1,b2,b3,b4) STR(a1) STR(a2) STR(a3) STR(a4) " + " STR(b1) STR(b2) STR(b3) STR(b4) " = overflow" 

void main() 
{ 
    printf("%s\n", 
     ADD_BIN_NUM(
        0,0,0,1, // first 4-bit int 
        1,0,1,1) // second 4-bit int 
        ); 

    printf("%s\n", 
     ADD_BIN_NUM(
        0,1,0,0, // first 4-bit int 
        0,1,0,1) // second 4-bit int 
       ); 

    printf("%s\n", 
     ADD_BIN_NUM(
        1,0,1,1, // first 4-bit int 
        0,1,1,0) // second 4-bit int 
       ); 
} 

Macro này có thể dễ dàng mở rộng để bổ sung hai inte 8 bit hoặc 16 bit hoặc 32 bit. Vì vậy, về cơ bản tất cả những gì chúng ta cần là các quy tắc nối và thay thế mã thông báo để đạt được kết quả đáng kinh ngạc với các macro.

EDIT: Tôi đã thay đổi định dạng kết quả và quan trọng hơn - Tôi đã thêm kiểm tra tràn.

HTH!

0

Tôi khá chắc rằng bộ tiền xử lý C/C++ chỉ sao chép và dán - nó không thực sự đánh giá bất kỳ biểu thức nào. Việc đánh giá biểu thức được thực hiện bởi trình biên dịch.

Để trả lời tốt hơn câu hỏi của bạn, bạn có thể muốn đăng những gì bạn đang cố gắng hoàn thành.

+6

Bộ tiền xử lý thực hiện một số đánh giá biểu thức. Các chỉ thị '# if' và' # elif' đều nhận các biểu thức phải thay thế macro và sau đó được đánh giá để xác định xem chúng có đánh giá đúng hay sai (hoặc một hoặc không, trong C). –

5

Tôi biết nó không phải là bộ tiền xử lý, nhưng nếu nó giúp, bạn có thể làm điều đó với các mẫu. Có lẽ bạn có thể sử dụng điều này kết hợp với một macro để đạt được những gì bạn cần.

#include <iostream> 
using namespace std; 

template <int N, int M> 
struct Add 
{ 
    static const int Value = N + M; 
}; 

int main() 
{ 
    cout << Add<4, 5>::Value << endl; 
    return 0; 
} 
+2

Tại sao không chỉ sử dụng 'Giá trị = N + M' bên trong' Thêm'? –

+0

@James: điểm tuyệt vời, cảm ơn. Tôi đã cập nhật phản hồi của mình. –

12

Các preprocessor hoạt động trên thẻ tiền xử lý và thời gian duy nhất mà nó đánh giá con số là trong việc đánh giá một chỉ thị #if hoặc #elif. Ngoài ra, con số không thực sự là con số trong quá trình tiền xử lý; chúng được phân loại là mã tiền xử lý mã thông báo, không thực sự là số.

Bạn có thể đánh giá số học cơ bản sử dụng nối mã thông báo:

#define ADD_0_0 0 
#define ADD_0_1 1 
#define ADD_1_0 1 
#define ADD_1_1 2 

#define ADD(x, y) ADD##_##x##_##y 

ADD(1, 0) // expands to 1 
ADD(1, 1) // expands to 2 

Thực sự, tuy nhiên, không có lý do để làm điều này, và nó sẽ là ngớ ngẩn để làm như vậy (bạn phải xác định một số lượng lớn các macro cho nó thậm chí còn hữu ích từ xa).

Nó sẽ là hợp lý hơn để có một macro mở rộng một biểu thức hằng số tích phân có thể được đánh giá bởi các trình biên dịch:

#define ADD(x, y) ((x) + (y)) 

ADD(1, 1) // expands to ((1) + (1)) 

Trình biên dịch sẽ có thể đánh giá sự biểu hiện 1 + 1.

+2

Tôi luôn muốn thấy ## làm một số công việc thực sự. – Tom

1

Trình tiền xử lý C có thể đánh giá các điều kiện có chứa số học số nguyên. Nó sẽ không thay thế các biểu thức số học và chuyển kết quả tới trình biên dịch, nhưng trình biên dịch sẽ đánh giá số học về các hằng số biên dịch và phát ra kết quả vào nhị phân, miễn là bạn không quá tải các toán tử đang được sử dụng.

1

Macro tiền xử lý không thể thực sự làm số học, nhưng chúng có thể được tận dụng một cách hữu ích để thực hiện toán học với các bảng liệt kê. Bí quyết chung là có một macro gọi các macro khác và có thể được lặp lại được gọi bằng cách sử dụng các định nghĩa khác nhau của các macro khác.

Ví dụ, một cái gì đó như:

 
#define MY_THINGS \ 
    a_thing(FRED,4) \ 
    a_thing(GEORGE,6) \ 
    a_thing(HARRY,5) \ 
    a_thing(HERMIONE,8) \ 
    a_thing(RON,3) \ 
    // This line left blank 

#define a_thing(name,size) EN_##name}; enum {EN_SIZE_##name=(size),EN_BLAH_##name = EN_##name+(size-1), 
enum {EN_FIRST_THING=0, MY_THINGS EN_TOTAL_SIZE}; 
#undef a_thing 

Điều đó sẽ cho phép một để 'phân bổ' một số tiền nhất định không gian cho mỗi điều trong ví dụ một mảng. Toán không được thực hiện bởi bộ tiền xử lý, nhưng các liệt kê vẫn được coi là hằng số biên dịch.

3

Dường như bạn có thể. Nếu bạn nhìn vào thư viện Boost Preprocessor, bạn có thể làm đủ mọi thứ với bộ tiền xử lý, thậm chí là số nguyên addition.

+0

Trình xử lý tiền tăng có (lần cuối tôi kiểm tra, một vài năm trước) tuân thủ kém với thông số kỹ thuật.Bit bổ sung không có trong spec. – EML

+1

@EML - Tôi không nói về thư viện Boost Wave, mà là việc triển khai bộ xử lý trước C/C++ mà bạn có thể sử dụng trong mã của mình, mà là thư viện Preprocessor Boost, sử dụng bộ tiền xử lý đã được tích hợp sẵn Trình biên dịch C/C++ để làm một số điều tuyệt vời. – Ferruccio

5

Có thể thực hiện bổ sung số nguyên bị chặn trong bộ tiền xử lý. Và, nó thực sự là cần thiết thường xuyên hơn một thực sự sẽ hy vọng, tức là, thay thế cho chỉ có ((2) + (3)) trong chương trình không hoạt động. (Ví dụ: bạn không thể có biến số được gọi là x((2)+(3))). Ý tưởng rất đơn giản: biến phần bổ sung thành số gia tăng mà bạn không quan tâm (quá nhiều) liệt kê tất cả chúng. Ví dụ:

#define INC(x) INC_ ## x 
#define INC_0 1 
#define INC_1 2 
#define INC_2 3 
#define INC_3 4 
#define INC_4 5 
#define INC_5 6 
#define INC_6 7 
#define INC_7 8 
#define INC_8 9 
#define INC_9 10 
INC(7) // => 8 

Bây giờ chúng tôi biết làm thế nào để làm ngoài việc lên đến 1.

#define ADD(x, y) ADD_ ## x(y) 
#define ADD_0(x) x 
#define ADD_1(x) INC(x) 
ADD(0, 2) // => 2 
ADD(1, 2) // => 3 

Để thêm số điện thoại để thậm chí lớn hơn, bạn cần một số loại "đệ quy".

#define ADD_2(x) ADD_1(INC(x)) 
#define ADD_3(x) ADD_2(INC(x)) 
#define ADD_4(x) ADD_3(INC(x)) 
#define ADD_5(x) ADD_4(INC(x)) 
#define ADD_6(x) ADD_5(INC(x)) 
#define ADD_7(x) ADD_6(INC(x)) 
#define ADD_8(x) ADD_7(INC(x)) 
#define ADD_9(x) ADD_8(INC(x)) 
#define ADD_10(x) ADD_9(INC(x)) 
ADD(5, 2) // => 7 

Tuy nhiên, người ta phải cẩn thận trong việc này. Ví dụ: các mục sau không hoạt động.

#define ADD_2(x) INC(ADD_1(x)) 
ADD(2, 2) // => INC_ADD_1(2) 

Đối với bất kỳ việc sử dụng mở rộng các thủ thuật như vậy, Boost Preprocessor là bạn của bạn.

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