informasi kontak saya
Surat[email protected]
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Ada beberapa pengaturan dalam bahasa CSimbol yang telah ditentukan sebelumnya, dapat digunakan secara langsung, simbol yang telah ditentukan sebelumnya adalah在预处理期间处理的
。
__FILE__ //进行编译的源文件
__LINE__ //文件当前的行号
__DATE__ //文件被编译日期
__TIME__ //文件被编译那一瞬的时间
__STDC__ //如果编译器遵循ANSI C(标准C),其值为1,否则未定义(报错)
Contoh:
#include<stdio.h>
int main()
{
printf("%sn", __FILE__);
printf("%dn", __LINE__);
printf("%sn", __DATE__);
printf("%sn", __TIME__);
return 0;
}
hasil operasi:
Saya ingin menyebutkan di sini bahwa VS tidak sepenuhnya mendukung ANSI C (standar C); gcc gccGcc Mendukung ANSI C (Standar C)
Sintaks dasar:
# define name stuff
Misalnya:
#define MAX 100
#define reg register // 为 register 这个关键字创建一个简短的名字
#define do_forever for(;;) //用更形象的符号来替换一种实现
#define CASE break;case //在写 case 语句的时候自动吧 break 写上
//如果定义的 stuff 过长,可以分成几行写,除了最后一行外,每行的后面都加一个反斜杠(续行符)
#define DEBUG_PRINT printf("file:%stline:%dt
date:%sttime:%sn" ,
__FILE__,__LINE__ ,
__DATE__,__TIME__ )
- Kalimat kedua adalah kemalasan, kenapa?
- Kalimat ketiga untuk untukFatau Bundar
初始化、判断、调整都可以省略
, tetapi jika penilaiannya dihilangkan, berarti kondisi penilaiannya selalu benar, yaituputaran tak terbatas- Sebaiknya hal ini tidak dilakukan pada game keempat, karena dapat dengan mudah menimbulkan masalah.
- Kalimat kelimakarakter kelanjutan garisIni untuk mencegah masalah setelah percabangan
转义
Kembali回车符
, sehingga pengangkutan kembali bukan lagi pengangkutan kembali.Tidak boleh ada apa pun setelah karakter kelanjutan baris, tekan“”
Tekan saja Enter, jika tidak maka kelanjutannya bukan baris kode berikut.
Sekarang masalahnya: gunakan # Definisikan definisikanDBahasa Inggris:Fdi dalamBahasa Inggris: Saat mendefinisikan pengenal, haruskah Anda menambahkannya di akhir?;
?
Misalnya:
#define MAX 1000
#define MAX 1000;
int main()
{
int n = MAX;
return 0;
}
Kode di atas ditambah;
, memang terkesan sedikit mubazir, namun tidak berdampak pada jalannya program.
Tampaknya menambahkan;
Atau jangan tambahkan;
Apakah akan baik-baik saja?
apakah benar seperti ini?
Mari kita lihat contoh berikut:
//例一
int main()
{
printf("%dn", MAX);
return 0;
}
//例二
int mian()
{
int max = 0;
if (1)
max = MAX;
else
max = 1;
return 0
}
Setelah penggantian:
printf("%dn", 1000;);
Mencetak1000;
Apa artinya?
if (1)
max = 1000;
;
else
max = 1;
yang lain yang lainBahasa Inggris:akumelihat Siapa yang cocok?
Soalnya, ada yang salah dengan ini, jadimenggunakan # Definisikan definisikanDBahasa Inggris:Fdi dalamBahasa Inggris: Saat mendefinisikan suatu indikator, jangan menambahkannya setelahnya;
# Definisikan definisikanDBahasa Inggris:Fdi dalamBahasa Inggris: Mekanisme tersebut mencakup ketentuan,允许把参数替换到文本中
, implementasi ini sering disebutMakro ( marco ) (marco)(sayarko)atau Definisikan makro ( definisikanmakro) (definisikanmakro)(DBahasa Inggris:Fdi dalamBahasa Inggris:sayamenyilang)
Perbedaan makro dengan pengidentifikasi definisi makro di atas adalah:Makro memiliki parameter
Berikut cara makro dideklarasikan:
#define name(parament - list) stuff
salah satu diantara mereka parament paramentPARsayaBahasa Inggris:NT - daftar daftarakuSayaST(daftar parameter) adalah daftar simbol yang dipisahkan koma yang mungkin muncul di barang barangSTkamkamutidak tengah
Catatan: parament paramentPARsayaBahasa Inggris:NT - daftar daftarakuSayaST(daftar parameter)Tanda kurung kiriHarus bersama nama namanamaBahasa Inggris: di sebelah, jika ada spasi di antara keduanya, daftar argumen ditafsirkan sebagai barang barangSTkamkamutidak bagian dari.
Contoh:
//实现一个宏,计算一个数的平方
#define SQUARE(x) x*x
int main()
{
int a = 5;
int ret = SQUARE(a);
printf("%dn", ret);
return 0;
}
hasil operasi:
Seperti yang Anda lihat, kuadrat 5 dihitung dengan benar
Namun nyatanya ada masalah pada kode di atas. Silakan lihat cuplikan kode berikut:
int a = 5;
printf("%dn", SQUARE(a + 1));
hasil operasi:
Mengapa demikian? Hasil dari 5+1 adalah 36, dan 6 ∗ * ∗ 6 seharusnya 36. Bagaimana kamu dapat 11?
Masalahnya ada pada makro, kita tahu宏是直接替换
, maka hasil langsung mengganti kode diatas adalah:
printf("%dn", a+1*a+1);
5 + 6 + 1, hasilnya tentu saja 11
Kita dapat dengan mudah mengatasi masalah ini dengan menambahkan tanda kurung di kedua sisi definisi makro.
#define SQUARE(x) (x)*(x)
Jadi apakah tidak ada masalah dengan definisi ini?Mari kita lihat definisi makro berikut
#define DOUBLE(X) (X)+(X)
Kami menggunakan tanda kurung dalam definisi untuk menghindari masalah sebelumnya, namun makro ini dapat menyebabkan kesalahan baru.
int a = 5;
printf("%dn", 10 * DOUBLE(a));
hasil operasi:
Hasil keluarannya bukan 100 melainkan 55. Alasannya masih sama seperti di atas Pertanyaan prioritas
Larutan:
#define DOUBLE(X) ((X)+(X))
Singkatnya, saat menggunakan makroJangan pernah berhemat pada tanda kurunguntuk menghindari interaksi yang tidak terduga antar operator dalam parameter atau operator yang berdekatan saat menggunakan makro.
Ketika parameter makro muncul lebih dari sekali dalam definisi makro, jika parameter tersebut memilikiefek samping, maka Anda mungkin berada dalam bahaya saat menggunakan makro ini, sehingga mengakibatkan不可预测
hasil dari. Efek samping adalah efek permanen ketika ekspresi dievaluasi.
Misalnya:
x + 1; //不带副作用
x++; //带副作用
Makro MAX berikut menunjukkan masalah yang disebabkan oleh parameter dengan efek samping.
#define MAX(a,b) ((a) > (b) ? (a):(b))
int main()
{
int x = 5;
int y = 8;
int z = MAX(x++, y++);
printf("x=%d, y=%d, z=%dn", x, y, z);
return 0;
}
hasil operasi:
Mengapa demikian?Mari kita analisa bersama
z = ((X++) > (y++) ? (x++) : (y++))
- Pertama buatlah penilaian: ukuran besarX++ dengan Y ykamu++ penilaian, karena merupakan postfix ++, saat menilai ukuran besarX adalah 5, Y ykamu adalah 8, 8 > 5
- Setelah menilai ukuran besarX adalah 6, Y ykamu untuk 9
- Kemudian jalankan Y ykamu ++, karena di postfix ++ maka hasilnya 9
- Kemudian lanjutkan Y ykamu Lakukan peningkatan otomatis, Y ykamu Hasil akhirnya adalah 10
kami akan ukuran besarX Dan Y ykamu Saat diteruskan ke makro, hasilnya terutama berubah Y ykamu, setelah dua perubahan, Anda bilang itu tidak buruk
Ketika parameter dengan efek samping diteruskan ke makro, dan parameter tersebut muncul lebih dari sekali di makro, efek samping parameter juga lebih dari satu kali.
Perluas dalam program # Definisikan definisikanDBahasa Inggris:Fdi dalamBahasa Inggris: Ada beberapa langkah yang terlibat saat mendefinisikan simbol dan makro
参数进行检查
, lihat apakah berisi # Definisikan definisikanDBahasa Inggris:Fdi dalamBahasa Inggris: Didefinisikan标识符
.Kalau iya, diganti dulu被插入
ke lokasi asli dalam program, dengan nama parameter makro diganti dengan nilainya#define MAX(a,b) ((a) > (b) ? (a):(b))
#define M 10
int main()
{
int x = 5;
int z = MAX(x, M);
return 0;
}
MAX pada kode di atas juga diwakili oleh # Definisikan definisikanDBahasa Inggris:Fdi dalamBahasa Inggris: DidefinisikanMakro .Pada pemeriksaan terakhir, parameter M-nya telah diganti kali ini.
MAKS ( x , 10 ) MAKS(x, 10)MAX(X,10) digantikan oleh ((x) > (10) ((x) > (10)((X)>(10)
?
?
? Bahasa Indonesia: (x): (10)) (x):(10))(X):(10))
tentu,宏里面嵌套宏
itu juga baik-baik saja
MAX(x, MAX(2, 3))
Saat ini, ganti makro terlebih dahulu di parameter, lalu ganti seluruh makro
Namun perlu diperhatikan bahwa ini不是递归
, yang hanya merupakan makro yang berfungsi sebagai argumen terhadap makro lainnya.递归是宏内部又调用了宏本身
。
Juga, ketika praprosesor mencari # Definisikan definisikanDBahasa Inggris:Fdi dalamBahasa Inggris: Saat mendefinisikan suatu simbol,Isi konstanta string tidak dicari
Maksudnya itu apa?Berikan saja kastanye dan Anda akan mengerti.
#define M 10
int main()
{
int x = 5;
int z = MAX(x, MAX(2, 3));
printf("M = %d", x);
return 0;
}
Dalam kode di atasprintf("M = %d", x);
tengah MMM tidak akan digantikan oleh 10
Makro di atas digunakan untuk mencari nilai lebih besar dari dua bilangan. Kita dapat menuliskannya sepenuhnya sebagai sebuah fungsi.
int Max(int x, int y)
{
return x > y ? x : y;
}
Kami menemukan bahwa semuanya mempunyai fungsi yang sama.Namun untuk fungsi "mencari bilangan terbesar dari dua bilangan", penulisannya akan menggunakan makro更有优势
Beberapa
Ada dua alasan:
- digunakan untuk
调用函数
Dan函数返回
darikodemungkin memerlukan waktu lebih lama daripada melakukan perhitungan kecil ini (saat memanggil fungsiBuat bingkai tumpukan ).Oleh karena itu, fungsi rasio makro ada di dalam program规模
Dan速度
Lebih baik dari yang pernah ada- Lebih penting
函数的参数必须声明类型
, yang menyebabkan fungsi hanya digunakan pada ekspresi dengan tipe yang sesuai.Sebaliknya, makro ini dapat diterapkan ke banyak tipe: integer, integer panjang, floating point, dll
>
Untuk membandingkan.Parameter makronya adalahKetik mandiridari。
Apakah kita akan selalu menggunakan makro di masa depan?Sebenarnya makro hanya digunakan untukPerhitungan sederhana, tidak cocok untuk operasi dan fungsi yang kompleks dan besar dibandingkan dengan makro Kekurangan:
- Setiap kali makro digunakan, salinan kode definisi makro dimasukkan ke dalam program.Kecuali jika makronya relatif pendek, hal itu mungkin terjadi
大幅度增加程序的长度
- makro adalah
没法调试
dari- Makro tidak bergantung pada tipe, yaitu,
不够严谨
- Makro dapat menyebabkan masalah prioritas operasi, menyebabkan program tersebut
容易出错
Namun terkadang, makro dapat melakukan hal-hal yang tidak dapat dilakukan oleh fungsi
Misalnya:
int* p = (int*)malloc(10 * sizeof * (int));
Kami tidak suka menulis seperti ini malok maloksayaIIok Fungsinya terlalu rumit, saya ingin大小
Dan类型
Berikan untuk membuka ruang
Malloc(10, int);
Bisakah fungsi melakukan ini?Tidak karenaFungsi tidak dapat meneruskan tipe
Dan makro bisa melakukannya, karena makro tidakJangan periksaparameter Andajenisdari
#define Malloc(n, type) (type*)malloc(n * sizeof(type))
int main()
{
int* p = Malloc(10, int);
return 0;
}
Perbandingan makro dan fungsi:
Atribut | # Definisikan definisikanDBahasa Inggris:Fdi dalamBahasa Inggris:Definisikan makro | fungsi |
---|---|---|
panjang kode | Setiap kali digunakan, kode makro akan dimasukkan ke dalam program. Kecuali makro yang sangat kecil, panjang program akan bertambah secara signifikan. | Nilai kode fungsi muncul di satu tempat, dan setiap kali fungsi digunakan, kode yang sama di tempat itu dipanggil. |
Kecepatan eksekusi | lebih cepat | Ada overhead tambahan dari pemanggilan dan pengembalian fungsi (membuka frame tumpukan), jadi mari kita mulai dengan yang lebih lambat. |
prioritas operator | Parameter makro dievaluasi dalam konteks semua ekspresi di sekitarnya. Kecuali jika tanda kurung disertakan, prioritas operator yang berdekatan mungkin memiliki konsekuensi yang tidak dapat diprediksi. Oleh karena itu, disarankan agar makro ditulis dengan lebih banyak tanda kurung. | Parameter fungsi hanya dievaluasi satu kali saat fungsi dipanggil, dan nilai hasilnya diteruskan ke fungsi, sehingga hasil evaluasi ekspresi lebih dapat diprediksi. |
Parameter dengan efek samping | Parameter dapat diganti ke beberapa posisi di makro. Jika parameter makro dievaluasi beberapa kali, evaluasi parameter dengan efek samping dapat menghasilkan hasil yang tidak terduga. | Parameter fungsi hanya dipanggil satu kali saat meneruskan parameter, dan hasilnya lebih mudah diprediksi. |
Tipe Parameter | Parameter makro tidak ada hubungannya dengan tipe. Selama operasi pada parameter legal, dia dapat digunakan untuk tipe parameter apa pun. | Parameter suatu fungsi berkaitan dengan tipe. Jika parameternya memiliki tipe yang berbeda, fungsi yang berbeda diperlukan, meskipun fungsi tersebut menjalankan tugas yang sama. |
men-debug | Makro tidak nyaman untuk di-debug | Fungsi dapat di-debug langkah demi langkah |
pengulangan | Makro tidak bisa bersifat rekursif | Fungsi bisa bersifat rekursif |
Apakah ada cara untuk menggabungkan kelebihannya?
Diperkenalkan di C++fungsi sebaris sebaris sebarisdi dalamakudi dalamBahasa Inggris: ——Memiliki keunggulan makro dan fungsi
Ini dijalankan secepat makro tetapi memiliki efek yang sama dengan suatu fungsi