#define STR1 "s"
#define STR2 "1"
#define STR3 STR1 ## STR2
Apakah mungkin untuk menggabungkan STR3 == "s1"? Anda dapat melakukan ini dengan meneruskan args ke fungsi Makro lainnya. Tetapi apakah ada cara langsung?
#define STR1 "s"
#define STR2 "1"
#define STR3 STR1 ## STR2
Apakah mungkin untuk menggabungkan STR3 == "s1"? Anda dapat melakukan ini dengan meneruskan args ke fungsi Makro lainnya. Tetapi apakah ada cara langsung?
Jawaban:
Jika keduanya adalah string, Anda bisa melakukan:
#define STR3 STR1 STR2
Praprosesor secara otomatis menggabungkan string yang berdekatan.
EDIT:
Seperti disebutkan di bawah ini, bukan preprocessor tetapi kompiler yang melakukan penggabungan.
L"a"
dan "b"
mendapatkan L"ab"
, tetapi Anda dapat menggabungkan L"a"
dan L"b"
mendapatkan L"ab"
.
Anda tidak memerlukan solusi semacam itu untuk string literal, karena mereka digabungkan pada tingkat bahasa, dan itu tidak akan berfungsi karena "s" "1" bukan token preprocessor yang valid.
[Sunting: Menanggapi komentar "Hanya untuk dicatat" yang salah di bawah ini yang sayangnya menerima beberapa suara positif, saya akan mengulangi pernyataan di atas dan mengamati bahwa fragmen program
#define PPCAT_NX(A, B) A ## B
PPCAT_NX("s", "1")
menghasilkan pesan kesalahan ini dari fase pra-pemrosesan gcc: kesalahan: menempelkan "" s "" dan "" 1 "" tidak memberikan token pra-pemrosesan yang valid
]
Namun, untuk penempelan token umum, coba ini:
/*
* 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)
Kemudian, misalnya, keduanya PPCAT_NX(s, 1)
dan PPCAT(s, 1)
menghasilkan pengenal s1
, kecuali jika s
didefinisikan sebagai makro, dalam hal ini PPCAT(s, 1)
menghasilkan <macro value of s>1
.
Melanjutkan tema adalah makro ini:
/*
* 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)
Kemudian,
#define T1 s
#define T2 1
STRINGIZE(PPCAT(T1, T2)) // produces "s1"
Sebaliknya,
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"
valid dalam C (dan C ++). Mereka adalah dua token (string literal) yang akan disatukan oleh kompiler dan ancaman sebagai satu token.
"s""1" isn't a valid token
- itu benar; itu, seperti yang Anda katakan, dua token. Tetapi menyatukannya dengan ## akan membuatnya menjadi token praproses tunggal , bukan dua token, sehingga compiler tidak akan melakukan penggabungan, melainkan lexer akan menolaknya (bahasa ini memerlukan diagnostik).
STRINGIZE_NX(whatever occurs here)
berkembang menjadi "apa pun yang terjadi di sini", terlepas dari definisi makro apa pun untuk apa pun, yang terjadi, atau di sini.
if A is defined as FRED then STRINGIZE_NX(A) still expands to "FRED"
- itu salah, dan tidak seperti ujian Anda. Anda berusaha keras untuk tidak memahami atau melakukan ini dengan benar, dan saya tidak akan menanggapi Anda lebih jauh.
Petunjuk: STRINGIZE
Makro di atas keren, tetapi jika Anda membuat kesalahan dan argumennya bukan makro - Anda memiliki kesalahan ketik pada namanya, atau lupa #include
pada file header - maka kompilator akan dengan senang hati memasukkan nama makro yang diklaim ke dalam string tanpa kesalahan.
Jika Anda bermaksud agar argumen ke STRINGIZE
selalu makro dengan nilai C normal, maka
#define STRINGIZE(A) ((A),STRINGIZE_NX(A))
akan mengembangkannya sekali dan memeriksa validitasnya, membuangnya, lalu mengembangkannya lagi menjadi string.
Butuh beberapa saat bagi saya untuk mencari tahu mengapa STRINGIZE(ENOENT)
berakhir sebagai "ENOENT"
alih-alih "2"
... Saya tidak memasukkan errno.h
.
,
operator yang tepat. :)
((1),"1") "." ((2),"2")
bukan hanya "1" "." "2")
STRINGIZE
definisi aslinya , "The value of ENOENT is " STRINGIZE(ENOENT)
berfungsi, sedangkan "The value of ENOENT is" STRINGIZE_EXPR(X)
menghasilkan kesalahan.