#define STR1 "s"
#define STR2 "1"
#define STR3 STR1 ## STR2
STR3 == "s1" ile birleştirmek mümkün mü? Bunu, başka bir Makro işlevine argümanlar aktararak yapabilirsiniz. Ama doğrudan bir yol var mı?
#define STR1 "s"
#define STR2 "1"
#define STR3 STR1 ## STR2
STR3 == "s1" ile birleştirmek mümkün mü? Bunu, başka bir Makro işlevine argümanlar aktararak yapabilirsiniz. Ama doğrudan bir yol var mı?
Yanıtlar:
Her ikisi de dizelerdeyse, şunları yapabilirsiniz:
#define STR3 STR1 STR2
Önişlemci, bitişik dizeleri otomatik olarak birleştirir.
DÜZENLE:
Aşağıda belirtildiği gibi, birleştirmeyi yapan ön işlemci değil derleyicidir.
L"a"ve "b"almak için L"ab", ama sen yapabilirsiniz bitiştirmek L"a"ve L"b"almak için L"ab".
Dize değişmezleri için bu tür bir çözüme ihtiyacınız yoktur, çünkü bunlar dil düzeyinde birleştirilir ve yine de çalışmaz çünkü "s" "1" geçerli bir önişlemci simgesi değildir.
[Düzenleme: Maalesef birkaç olumlu oy almış olan aşağıdaki yanlış "Sadece kayıt için" yorumuna yanıt olarak, yukarıdaki ifadeyi tekrarlayacağım ve program parçasının
#define PPCAT_NX(A, B) A ## B
PPCAT_NX("s", "1")
gcc'nin ön işleme aşamasından bu hata mesajını üretir: hata: "" s "" ve "" 1 "" öğelerinin yapıştırılması geçerli bir ön işleme jetonu vermez
]
Ancak, genel simge yapıştırmak için şunu deneyin:
/*
* Concatenate preprocessor tokens A and B without expanding macro definitions
* (however, if invoked from a macro, macro arguments are expanded).
*/
#define PPCAT_NX(A, B) A ## B
/*
* Concatenate preprocessor tokens A and B after macro-expanding them.
*/
#define PPCAT(A, B) PPCAT_NX(A, B)
Daha sonra, örneğin, her ikisi de PPCAT_NX(s, 1)ve PPCAT(s, 1)tanımlayıcı üretmek s1sürece, sbir kasa, bir makro olarak tanımlanmaktadır, PPCAT(s, 1)oluşturur <macro value of s>1.
Temada devam eden şu makrolar:
/*
* Turn A into a string literal without expanding macro definitions
* (however, if invoked from a macro, macro arguments are expanded).
*/
#define STRINGIZE_NX(A) #A
/*
* Turn A into a string literal after macro-expanding it.
*/
#define STRINGIZE(A) STRINGIZE_NX(A)
Sonra,
#define T1 s
#define T2 1
STRINGIZE(PPCAT(T1, T2)) // produces "s1"
Aksine,
STRINGIZE(PPCAT_NX(T1, T2)) // produces "T1T2"
STRINGIZE_NX(PPCAT_NX(T1, T2)) // produces "PPCAT_NX(T1, T2)"
#define T1T2 visit the zoo
STRINGIZE(PPCAT_NX(T1, T2)) // produces "visit the zoo"
STRINGIZE_NX(PPCAT(T1, T2)) // produces "PPCAT(T1, T2)"
"s""1"C (ve C ++) 'da geçerlidir. Derleyicinin kendisini bir araya getirip tek bir belirteç olarak tehdit edeceği iki simgedir (string değişmezleri).
"s""1" isn't a valid token- bu doğru; dediğiniz gibi, iki jeton. Ancak bunları ## ile birlikte birleştirmek, onları iki jeton değil, tek bir ön işleme jetonu haline getirir ve böylece derleyici birleştirme yapmaz, bunun yerine sözcü bunları reddeder (dil bir teşhis gerektirir).
STRINGIZE_NX(whatever occurs here), her ne olursa olsun, meydana gelen veya burada herhangi bir makro tanımlamadan bağımsız olarak "burada ne olursa olsun" şeklinde genişler.
if A is defined as FRED then STRINGIZE_NX(A) still expands to "FRED"- bu yanlış ve testiniz gibi değil. Bunu anlamamak veya doğru anlamamak için çok uğraşıyorsun ve ben sana daha fazla cevap vermeyeceğim.
İpucu: Yukarıdaki STRINGIZEmakro harikadır, ancak bir hata yaparsanız ve argümanı bir makro değilse - adda bir yazım hatası yapmışsanız veya #includebaşlık dosyasını unuttuysanız - derleyici, sözde makro adını mutlu bir şekilde hatasız dize.
Argümanının STRINGIZEher zaman normal C değerine sahip bir makro olmasını amaçlıyorsanız, o zaman
#define STRINGIZE(A) ((A),STRINGIZE_NX(A))
bir kez genişletir ve geçerliliğini kontrol eder, atar ve sonra tekrar bir dizeye genişletir.
Dahil etmemiştim yerine neden STRINGIZE(ENOENT)bittiğini anlamam biraz zaman aldı ."ENOENT""2"errno.h
,Operatörün doğru kullanımı için önemli gözlem ve +1 . :)
((1),"1") "." ((2),"2")sadece "1" "yerine" "2" gibi dizilerle sonuçlanır )
STRINGIZEtanımla "The value of ENOENT is " STRINGIZE(ENOENT)çalışır, oysa "The value of ENOENT is" STRINGIZE_EXPR(X)bir hata üretir.