mentre non è possibile utilizzare una macro per definire un'altra macro, a seconda di ciò che si sta cercando di ottenere, è possibile utilizzare le macro per ottenere effettivamente la stessa cosa facendole definire costanti. per esempio, ho una vasta libreria di macro c che uso per definire stringhe costanti oggettive C e valori chiave.
Ecco alcuni frammenti di codice di alcune delle mie intestazioni.
// 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__)
e un esempio di utilizzo che invoca:
#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);
l'ultima parte può essere un po 'difficile da ottenere la testa intorno. la macro sw_Logging_defineKeys() definisce un elenco che prende il nome di una macro come parametro (defineKeyValue), quindi viene utilizzato per richiamare la macro che esegue il processo di definizione effettivo. cioè, per ogni elemento nell'elenco, il nome della macro passato viene utilizzato per definire il contesto ("intestazione" o "implementazione", ad esempio il file "h" o "m", se si comprendono le estensioni di file obiettivo c) mentre questo è usato per l'obiettivo c, è semplicemente semplice macro c vecchio, usato per uno "scopo più alto" del possibile Kernighan and Richie mai immaginato. :-)
Modificare il frammento in modo che abbia la possibilità di compilazione; e prova a compilarlo. Che succede? Anch'io sono curioso. –
@PeteWilson Tentativo di compilare il codice sopra, ottengo 'errore: '#' non è seguito da un parametro macro' come errore – Linsey
+1 per" perché dovrei farlo? " :-) –