Rumah >pembangunan bahagian belakang >C++ >#define INC(a) INC(a ?
Adakah makro ini merosakkan GCC? Baca dan anda akan dapat jawapannya
Matlamat artikel ini adalah untuk memperkenalkan anda kepada dunia makro yang mengagumkan dalam C.
Dalam C, baris yang bermula dengan # ditafsirkan oleh pengkompil semasa menyusun fail sumber. Ini dipanggil arahan prapemproses. Makro adalah salah satu daripadanya.
Titik sejarah kecil:
Makro bahasa C telah diperkenalkan dengan standard bahasa C yang pertama, dipanggil ANSI C (atau C89),
yang telah diseragamkan oleh American National Standards Institute (ANSI) pada tahun 1989.Walau bagaimanapun, sebelum penyeragaman ini, makro telah pun menjadi sebahagian daripada bahasa C (atau K&R C) yang digunakan pada tahun 1970-an
Pengkompil C asal, yang dibangunkan oleh Dennis Ritchie untuk sistem pengendalian UNIX, telah pun menyertakan bentuk asas makro melalui prapemproses, membenarkan takrifan dengan #define.
#define SENS_DE_LA_VIE 3.14 /* ... */ printf("%f\n", SENS_DE_LA_VIE);
Define berfungsi dengan mudah untuk difahami: pengkompil menggantikan semua kejadian dalam kod dengan nilai yang ditentukan. Ia berfungsi dengan sintaks berikut #define
Sedikit seperti "Ctrl-f dan ganti".
Kami boleh menggunakan defines untuk mentakrifkan fungsi yang boleh kami gunakan dalam kod kami.
#define INC(a) a++ #define MULTI_LINE(a,b) a = b; \ b = 0; INC(my_variable); MULTI_LINE(my_variable, foobar) // Je souligne le fait qu'il peut ne pas y avoir de ';' en fin de ligne // Cela donnera my_variable++; my_variable = foobar; foobar = 0;
Kami boleh mengisytiharkan makro secara bersyarat.
Jika nama sudah ditakrifkan maka kami melaksanakan sekeping kod berikut.
#ifdef DEBUG // Je souligne qu'il est rarement conseillé d'utiliser des printf() en debug // et que nous avons brisé la règle du nom des macros en MAJ. #define return printf("(%s:%d)\n", __FUNCTION__, __LINE__); return #endif /* ! DEBUG */ int main(void) { return 1; }
Dalam kes ini, saya menggunakan #ifndef, tetapi ia juga wujud:
#if (X == 1) #define Y 2 #elif (X == 2) #define Y "Ami de la bonne blague, bonjour !" #else #define Y NULL #endif /* ! X */ /* ... */ int main(void) { #if (X == 1) printf("%d\n", Y); #elif (X == 2) printf("%s\n", Y); #else printf("%p\n", Y); #endif /* ! X */ }
Kami suka memberi isyarat penamat #jika dengan ulasan pukal. Ini adalah konvensyen yang membolehkan anda menavigasi kod dengan lebih baik.
Anda boleh lihat dalam contoh sebelumnya bahawa saya menggunakan kata kunci __FUNCTION__ dan __LINE__.
Seperti yang anda jangkakan, ini adalah makro yang akan digantikan oleh pengkompil dengan nilai yang betul.
Terdapat senarai makro Pratetap Biasa.
Perhatikan bahawa terdapat apa yang dipanggil makro khusus Sistem.
Senarai kecil yang tidak lengkap:
#define SENS_DE_LA_VIE 3.14 /* ... */ printf("%f\n", SENS_DE_LA_VIE);
Di sini, kita dapat melihat bahawa kita menjana makro variadik, terutamanya berguna apabila membuat log.
(Walaupun bukan idea yang baik untuk membuat log dengan printfs.)
Untuk ini, kita perlu mencipta fail luaran, sering dinamakan *.def walaupun tiada konvensyen.
#define INC(a) a++ #define MULTI_LINE(a,b) a = b; \ b = 0; INC(my_variable); MULTI_LINE(my_variable, foobar) // Je souligne le fait qu'il peut ne pas y avoir de ';' en fin de ligne // Cela donnera my_variable++; my_variable = foobar; foobar = 0;
#ifdef DEBUG // Je souligne qu'il est rarement conseillé d'utiliser des printf() en debug // et que nous avons brisé la règle du nom des macros en MAJ. #define return printf("(%s:%d)\n", __FUNCTION__, __LINE__); return #endif /* ! DEBUG */ int main(void) { return 1; }
Makro jenis ini amat berguna. Saya mesti mengakui bahawa ia jarang ditemui dalam kod sumber, tetapi ia membolehkan anda mengubah suai operasi program tanpa perlu mengubah suai kod sumber. Fakta yang menyeronokkan, ia sering digunakan dalam penciptaan biji. Ia membolehkan anda menjana struktur global seperti IDT dan GDT.
Perhatian: Penjelasan pantas dahulu, makro ialah alat yang hebat tetapi anda perlu berhati-hati. Anda semestinya tidak boleh menggunakan makro jenis ini:
#if (X == 1) #define Y 2 #elif (X == 2) #define Y "Ami de la bonne blague, bonjour !" #else #define Y NULL #endif /* ! X */ /* ... */ int main(void) { #if (X == 1) printf("%d\n", Y); #elif (X == 2) printf("%s\n", Y); #else printf("%p\n", Y); #endif /* ! X */ }
Mari kita ambil contoh: MIN(2 5, fibo(25))
MIN(2 5, fibo(25)) => (2 5 < fibo(25) ? 2 5: fibo(25))
Di sini masalahnya ialah keutamaan pengiraan. Pengkompil terlebih dahulu akan melakukan perbandingan kemudian penambahan, oleh itu 2 (1). Kami membetulkannya dengan menambahkan kurungan menggunakan argumen makro.
// Ici, l'opérateur ## est l'opérateur de concaténation #define DEBUG_PRNTF(fmt, ...) printf("LOG" ## fmt, __VA_ARGS__);
Memandangkan anda tidak pernah tahu perkara yang pengguna anda akan luluskan sebagai parameter, sentiasa letakkan kurungan pada hujah.
MIN(2 5, fibo(25)) => (2 5 < fibo(25) ? 2 5: fibo(25))
Kami mendapati bahawa pengkompil membuat penggantian yang bodoh dan jahat, yang bermaksud bahawa kami akan mengira fibo(25) dua kali. Saya akan membiarkan anda bayangkan jika ia adalah pelaksanaan rekursif.
Untuk menyelesaikan masalah ini, kami mengisytiharkan pembolehubah perantaraan sebelum if.
// color.def X(NC, "\e[0m", "No Color", 0x000000) X(BLACK, "\e[0;30m", "Black", 0x000000) X(GRAY, "\e[1;30m", "Gray", 0x808080) X(RED, "\e[0;31m", "Red", 0xFF0000) X(LIGHT_RED, "\e[1;31m", "Light Red", 0xFF8080) X(GREEN, "\e[0;32m", "Green", 0x00FF00) X(LIGHT_GREEN, "\e[1;32m", "Light Green", 0x80FF80) X(BROWN, "\e[0;33m", "Brown", 0xA52A2A) X(YELLOW, "\e[1;33m", "Yellow", 0xFFFF00) X(BLUE, "\e[0;34m", "Blue", 0x0000FF) X(LIGHT_BLUE, "\e[1;34m", "Light Blue", 0xADD8E6) X(PURPLE, "\e[0;35m", "Purple", 0x800080) X(LIGHT_PURPLE, "\e[1;35m", "Light Purple", 0xEE82EE) X(CYAN, "\e[0;36m", "Cyan", 0x00FFFF) X(LIGHT_CYAN, "\e[1;36m", "Light Cyan", 0xE0FFFF) X(LIGHT_GRAY, "\e[0;37m", "Light Gray", 0xD3D3D3) X(WHITE, "\e[1;37m", "White", 0xFFFFFF)
Di sini, ia adalah kod berlebihan semata-mata untuk keseronokan. Saya tidak semestinya menasihati anda untuk menggunakan makro ini dalam kod anda.
Saya hanya berseronok (perkara yang baik dalam hidup).
typedef struct { const char *name; const char *ansi_code; const char *description; unsigned int rgb; } Color; #define X(NAME, ANSI, DESC, RGB) { #NAME, ANSI, DESC, RGB }, Color colors[] = { #include "color.def" }; #undef X #define X(NAME, ANSI, DESC, RGB) printf("%s (%s) = %s\n", #NAME, DESC, #RGB); void print_colors() { // Bien entendu, on pourrait itérer sur la structure créée mais c'est une illustration #include "color.def" } #undef X
Saya akan membenarkan anda menguji dengan sedikit -fsanitize=address. Ia benar-benar gila. Kami juga dapat melihat peningkatan pada fungsi auto_free yang mengambil sebagai parameter rentetan aksara nama struktur kami untuk membuat suis.
Fungsi chiller di mana kita hanya mengira masa pelaksanaan fungsi kita. Sangat berguna untuk penanda aras.
#define SENS_DE_LA_VIE 3.14 /* ... */ printf("%f\n", SENS_DE_LA_VIE);
Makro X kecil yang mengambil makro sebagai hujah dan mengembangkannya.
#define INC(a) a++ #define MULTI_LINE(a,b) a = b; \ b = 0; INC(my_variable); MULTI_LINE(my_variable, foobar) // Je souligne le fait qu'il peut ne pas y avoir de ';' en fin de ligne // Cela donnera my_variable++; my_variable = foobar; foobar = 0;
Di sini, kami sebenarnya menjana keseluruhan fungsi dengan makro, kerana C tidak mempunyai had. Saya juga?
#ifdef DEBUG // Je souligne qu'il est rarement conseillé d'utiliser des printf() en debug // et que nous avons brisé la règle du nom des macros en MAJ. #define return printf("(%s:%d)\n", __FUNCTION__, __LINE__); return #endif /* ! DEBUG */ int main(void) { return 1; }
Kini tiba masanya untuk menyelesaikan masalah. Kami melihat banyak perkara yang sangat menarik. Dan jika anda pernah tergoda, anda bebas untuk menemui makro untuk diri sendiri. Masih banyak perkara yang boleh dilihat.
Jadi, kesimpulan: RTFM.
PS: Bagi tajuk, makro bukan rekursif, ia hanya berkembang dengan kedalaman 1 dan dalam kes kami sekarang, GCC akan membuat pengisytiharan_implisit pada INC dan ranap sistem.
Atas ialah kandungan terperinci #define INC(a) INC(a ?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!