2010-09-03 20 views
6

Tôi đang cố xác định macro để tạo tên mã thông báo, chứa biến.C Macro Token Ghép liên quan đến một biến - là nó có thể?

Về cơ bản, những gì tôi đang cố gắng là thế này:

#define GLUER(x,y,z) x##y##z 
#define PxDIR(x) GLUER(P,x,DIR) 

int main() { 
    int port; 
    port = 2; 
    PxDIR(port) |= 0x01; 
} 

tôi hy vọng để tạo ra P2DIR mã thông báo trong tuyên bố trên, nhưng theo đầu ra trình biên dịch của tôi, nó tạo ra các PportDIR thẻ, đó là KHÔNG những gì tôi muốn. Bất kỳ trợ giúp ở đây? Hoặc là những gì tôi đang cố gắng để làm không thể?

+0

Bạn có ý định thực hiện '#define port 2' không? – Gabe

Trả lời

6

Tôi không nghĩ rằng những gì bạn đang cố gắng làm là có thể. Các macro C thực sự là các macro tiền xử lý được mở rộng trước khi biên dịch. Biến số port, không được đặt cho đến khi chạy.

+0

Cảm ơn, đó là những gì tôi đã suy nghĩ. Nó đã được một thời gian kể từ khi tôi đã thực hiện thẳng C. – gatesphere

3

Điều đó là không thể. Các bộ tiền xử lý C hoạt động bằng cách xử lý mã thông báo và chúng không thực hiện bất kỳ độ phân giải hoặc thay thế nào cần kiến ​​thức về cơ chế của ngôn ngữ (ngoại trừ số học cơ bản liên quan đến chữ số nguyên, ngoài đầu của tôi). Hãy xem xét, ví dụ, các tài liệu cho tiền xử lý của GCC regarding tokenisation. Chỉ một trình biên dịch sẽ biết phải làm gì với biến "cổng".

Một giải pháp là phải làm một cái gì đó như:

#define PxDIR(var, portnum) do { \ 
    var = portnum; \ 
    P##portnum##DIR |= blah; \ 
} while(0) 

... và sau đó ...

int port; 
PxDIR(port, 2); 

tôi để lại nó cho bạn để làm điều này không phải là xấu xí hay hacky vì nó là ở đây (và tổng quát hơn, tùy thuộc vào những gì bạn cần) :)

+0

Cảm ơn. Tôi đã xem xét nó như một cách để giảm bloat mã trong một dự án nhúng, nhưng có vẻ như nó không thể sử dụng một biến để giải quyết vấn đề này. Ah tốt. Cảm ơn một lần nữa! – gatesphere

+0

@ user438605 Thật vậy - mặc dù bạn có thể muốn xem [X Macro Idiom] (http://www.drdobbs.com/184401387) để tạo mã lặp lại. – detly

2

... hoặc chỉ làm cho PORT cũng là một macro:

#define PORT 2 
#define GLUER(x,y,z) x##y##z 
#define PxDIR(x) GLUER(P,x,DIR) 

int main() { 
    PxDIR(PORT) |= 0x01; 
    return 0; 
} 
0

Những gì bạn đang cố gắng làm không có ý nghĩa.

#define GLUER(x,y,z) x##y##z 
#define PxDIR(x) GLUER(P,x,DIR) 

int main() { 
    int port; 
    port = 2; 
    PxDIR(port) |= 0x01; 
} 

Bộ tiền xử lý được chạy lúc (trước) thời gian biên dịch. Vì vậy, nó không thể biết bất cứ điều gì về nội dung của biến số port. Bộ tiền xử lý yêu cầu bất kỳ giá trị nào được truyền dưới dạng đối số cho macro là các hằng số. Ví dụ, bạn có thể làm như sau:

#define GLUER(x,y,z) x##y##z 
#define PxDIR(x) GLUER(P,x,DIR) 

int main() { 
    PxDIR(2) |= 0x01; //setup port 2 
} 

Ngược lại, nếu bạn muốn để có thể vượt qua một biến để macro này thực sự là cách duy nhất là để đảm bảo mã để làm như vậy được tạo ra một cách rõ ràng:

#define GLUER(x,y,z) x##y##z 
#define PxDIR(x) GLUER(P,x,DIR) 

uint16_t* get_port_pointer(uint8_t port_id) { 
    if (port == 0) { 
    return &PxDIR(0); 
    } else if (port == 1) { 
    return &PxDIR(1); 
    } else if (port == 2) { 
    return &PxDIR(2); 
    } else if (port == 3) { 
    return &PxDIR(3); 
    } else { 
    return &0; 
    } 
} 

int main() { 
    int port; 
    port = 2; 

    *(get_port_pointer(port)) |= 0x01; 
} 

Bằng cách này, chúng tôi đảm bảo có mã cho bất kỳ cổng nào từ 0 đến 3 được truy cập. Ngoài ra, bây giờ chúng ta phải xem ra các con trỏ null được trả về từ hàm get_port_pointer.

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