2011-09-24 36 views
7

Có thể xác định macro tắt nội dung của macro không?Xác định macro tắt nội dung của macro

Ví dụ:

#define SET(key,value) #define key value 

SET(myKey,"value") 

int main(){ 
    char str[] = myKey; 
    printf("%s",str); 
} 

sẽ cho kết quả trong

int main(){ 
    char str[] = "value"; 
    printf("%s",str); 
} 

sau khi được xử lý trước.

Tại sao tôi nên làm điều này? Vì tôi rất tò mò;)

+0

Sửa mảnh của bạn để nó có cơ hội biên soạn; và cố gắng biên dịch nó. Chuyện gì xảy ra? Tôi cũng tò mò. –

+2

@PeteWilson Cố gắng biên dịch mã ở trên, tôi nhận được 'lỗi: '#' không được theo sau bởi tham số macro' dưới dạng lỗi – Linsey

+0

+1 cho" tại sao tôi làm điều này? " :-) –

Trả lời

5

Không, không thể xác định macro trong macro khác.

2

Bộ tiền xử lý chỉ lặp lại một lần trước trình biên dịch. Những gì bạn đang đề xuất sẽ yêu cầu số lần lặp lại không xác định.

+0

Bộ tiền xử lý không xác định các macro chỉ một lần. Bộ tiền xử lý cho phép bạn # macro undef' và '# define' nhiều lần. Nó thay đổi và chỉnh sửa các macro trong suốt quá trình xử lý, không có gì ngăn nó chỉnh sửa các quy tắc này bên trong các macro. – Linsey

+0

Điều mà bộ tiền xử lý thực hiện là "chuyển qua tất cả các tệp và thay thế một số chuỗi" theo một thứ tự nào đó. Thực tế là có một thứ tự cho phép nó có bộ nhớ và #undef #ifdef vv ... Tuy nhiên để có được chuỗi được thay thế như một macro sẽ yêu cầu đệ quy. – Willy

+0

bạn có thể vui lòng cung cấp một ví dụ. Tôi đồng ý đệ quy sẽ được yêu cầu nếu bạn muốn thay thế văn bản trước '# define' bên trong, nhưng nếu mã có hiệu lực từ điểm trên có vẻ không phải là một vấn đề. – Linsey

0

Macro là một thay thế văn bản đơn giản. Việc tạo ra các chỉ thị tiền xử lý mới từ một macro sẽ yêu cầu bộ tiền xử lý tiếp tục tiền xử lý từ số bắt đầu từ của sự thay thế. Tuy nhiên, tiền xử lý được xác định chuẩn để tiếp tục sau số thay thế.

Điều này có ý nghĩa từ điểm phát trực tuyến, xem mã chưa xử lý dưới dạng luồng đầu vào và mã được xử lý (và được thay thế) làm luồng đầu ra. Thay thế vĩ mô có thể có độ dài tùy ý, có nghĩa là cho việc xử lý trước từ đầu rằng một số lượng ký tự tùy ý phải được chèn vào đầu luồng đầu vào để được xử lý lại.

Khi quá trình xử lý tiếp tục sau thay thế, đầu vào chỉ được xử lý trong một lần chạy mà không cần chèn hoặc đệm, vì mọi thứ đều trực tiếp xuất ra.

0

trong khi không thể sử dụng macro để xác định macro khác, tùy thuộc vào những gì bạn đang tìm kiếm để đạt được, bạn có thể sử dụng macro để đạt được điều tương tự bằng cách xác định hằng số. ví dụ, tôi có một thư viện mở rộng của các macro c tôi sử dụng để xác định các chuỗi cố định C và các giá trị khóa.

đây là một số đoạn mã từ một số tiêu đề của tôi.

// use defineStringsIn_X_File to define a NSString constant to a literal value. 
// usage (direct) : defineStringsIn_X_File(constname,value); 

#define defineStringsIn_h_File(constname,value) extern NSString * const constname; 
#define defineStringsIn_m_File(constname,value) NSString * const constname = value; 


// use defineKeysIn_X_File when the value is the same as the key. 
// eg myKeyname has the value @"myKeyname" 
// usage (direct) : defineKeysIn_X_File(keyname); 
// usage (indirect) : myKeyDefiner(defineKeysIn_X_File); 
#define defineKeysIn_h_File(key) defineStringsIn_h_File(key,key) 
#define defineKeysIn_m_File(key) defineStringsIn_m_File(key,@#key) 



// use defineKeyValuesIn_X_File when the value is completely unrelated to the key - ie you supply a quoted value. 
// eg myKeyname has the value @"keyvalue" 
// usage: defineKeyValuesIn_X_File(keyname,@"keyvalue"); 
// usage (indirect) : myKeyDefiner(defineKeyValuesIn_X_File); 
#define defineKeyValuesIn_h_File(key,value) defineStringsIn_h_File(key,value) 
#define defineKeyValuesIn_m_File(key,value) defineStringsIn_m_File(key,value) 



// use definePrefixedKeys_in_X_File when the last part of the keyname is the same as the value. 
// eg myPrefixed_keyname has the value @"keyname" 
// usage (direct) : definePrefixedKeys_in_X_File(prefix_,keyname); 
// usage (indirect) : myKeyDefiner(definePrefixedKeys_in_X_File); 

#define definePrefixedKeys_in_h_File_2(prefix,key) defineKeyValuesIn_h_File(prefix##key,@#key) 
#define definePrefixedKeys_in_m_File_2(prefix,key) defineKeyValuesIn_m_File(prefix##key,@#key) 

#define definePrefixedKeys_in_h_File_3(prefix,key,NSObject) definePrefixedKeys_in_h_File_2(prefix,key) 
#define definePrefixedKeys_in_m_File_3(prefix,key,NSObject) definePrefixedKeys_in_m_File_2(prefix,key) 

#define definePrefixedKeys_in_h_File(...) VARARG(definePrefixedKeys_in_h_File_, __VA_ARGS__) 
#define definePrefixedKeys_in_m_File(...) VARARG(definePrefixedKeys_in_m_File_, __VA_ARGS__) 




// use definePrefixedKeyValues_in_X_File when the value has no relation to the keyname, but the keyname has a common prefixe 
// eg myPrefixed_keyname has the value @"bollocks" 
// usage: definePrefixedKeyValues_in_X_File(prefix_,keyname,@"bollocks"); 
// usage (indirect) : myKeyDefiner(definePrefixedKeyValues_in_X_File); 
#define definePrefixedKeyValues_in_h_File(prefix,key,value) defineKeyValuesIn_h_File(prefix##key,value) 
#define definePrefixedKeyValues_in_m_File(prefix,key,value) defineKeyValuesIn_m_File(prefix##key,value) 







#define VA_NARGS_IMPL(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, N, ...) N 
#define VA_NARGS(...) VA_NARGS_IMPL(X,##__VA_ARGS__, 11, 10,9, 8, 7, 6, 5, 4, 3, 2, 1, 0) 
#define VARARG_IMPL2(base, count, ...) base##count(__VA_ARGS__) 
#define VARARG_IMPL(base, count, ...) VARARG_IMPL2(base, count, __VA_ARGS__) 
#define VARARG(base, ...) VARARG_IMPL(base, VA_NARGS(__VA_ARGS__), __VA_ARGS__) 

và một ví dụ sử dụng để gọi nó:

#define sw_Logging_defineKeys(defineKeyValue) \ 
/** start of key list for sw_Logging_ **/\ 
/**/defineKeyValue(sw_Logging_,log)\ 
/**/defineKeyValue(sw_Logging_,time)\ 
/**/defineKeyValue(sw_Logging_,message)\ 
/**/defineKeyValue(sw_Logging_,object)\ 
/**/defineKeyValue(sw_Logging_,findCallStack)\ 
/**/defineKeyValue(sw_Logging_,debugging)\ 
/**/defineKeyValue(sw_Logging_,callStackSymbols)\ 
/**/defineKeyValue(sw_Logging_,callStackReturnAddresses)\ 
/** end of key list for sw_Logging_ **/ 
sw_Logging_defineKeys(definePrefixedKeys_in_h_File); 

phần cuối cùng có thể là một chút khó khăn để có được đầu của bạn xung quanh. macro sw_Logging_defineKeys() xác định danh sách lấy tên của macro vì tham số (defineKeyValue) này sau đó được sử dụng để gọi macro thực hiện quy trình định nghĩa thực tế. tức là, đối với mỗi mục trong danh sách, tên macro được truyền vào được sử dụng để xác định ngữ cảnh ("tiêu đề" hoặc "triển khai", ví dụ: "h" hoặc "m" tệp, nếu bạn hiểu mục tiêu tệp c mục tiêu) trong khi điều này được sử dụng cho mục tiêu c, nó chỉ đơn giản là các macro c cũ, được sử dụng cho một "mục đích cao hơn" hơn có thể là Kernighan and Richie từng được dự tính. :-)

1

Không, bạn không thể - # trong danh sách thay thế macro có nghĩa là TIẾP TỤC TIẾP THEO QUOTE.Đó là một vấn đề chính tả hơn bất kỳ câu đố lôgic nào :)

(Nếu bạn yêu cầu loại giải pháp này trong mã của bạn, hơn là cách và thủ thuật sử dụng macro, nhưng bạn cần phải cụ thể về các trường hợp sử dụng cần - như ví dụ của bạn có thể đạt được bằng cách định nghĩa: #define MyKey "value")

Dưới đây là từ các tiêu chuẩn ansi C99

6.10.3.2 The # operator

Constraints

1 Each # preprocessing token in the replacement list for a function-like macro shall be followed by a parameter as the next preprocessing token in the replacement list. Semantics 2 If, in the replacement list, a parameter is immediately preceded by a # preprocessing token, both are replaced by a single character string literal preprocessing token that contains the spelling of the preprocessing token sequence for the corresponding argument. Each occurrence of white space between the argument’s preprocessing tokens becomes a single space character in the character string literal. White space before the first preprocessing token and after the last preprocessing token composing the argument is deleted. Otherwise, the original spelling of each preprocessing token in the argument is retained in the character string literal, except for special handling for producing the spelling of string literals and character constants: a \ character is inserted before each " and \ character of a character constant or string literal (including the delimiting " characters), except that it is implementation-defined whether a \ character is inserted before the \ character beginning a universal character name. If the replacement that results is not a valid character string literal, the behavior is undefined. The character string literal corresponding to an empty argument is "". The order of evaluation of # and ## operators is unspecified.

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