ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

浅谈C++/C关于#define的那些奇奇怪怪的用法

浅谈C++/C关于#define的那些奇奇怪怪的用法 前言众所周知#define(也就是宏定义)在C/C里用处很广泛。对于一个萌新小白来说宏定义有以下几种用法1 缩减代码第一种用法与typedef类似而且比typedef应用得更广泛。举个例子在以下C程序中unsigned int出现的实在是太多了。12345678910111213141516171819#includebits/stdc.husingnamespacestd;unsignedintn;intmain(){cinn;for(unsignedinti0;in;i){unsignedinta,b;cinab;while(b0){unsignedintra%b;ab;br;}coutaendl;}return0;}那该怎么办呢其实只需要加一行这样的代码然后再把unsigned int改成ui就可以了。1#define ui unsigned int这样的话程序就简短了很多。123456789101112131415161718192021#includebits/stdc.h#define ui unsigned int//也可以写作typedef unsigned int uiusingnamespacestd;ui n;intmain(){cinn;for(ui i0;in;i){ui a,b;cinab;while(b0){ui ra%b;ab;br;}coutaendl;}return0;}2 定义变量第二种用法与const auto(不一定是int)相似。当我们想写一段这样的代码时我们可以用const int写以避免重复出现10000512345678910111213#includebits/stdc.husingnamespacestd;constintN100005;inta[N],b[N],c[N],ans[N];intmain(){intn;cinn;for(inti0;in;i) cina[i]b[i]c[i];for(inti0;in;i) ans[i]a[i]b[i]-c[i];for(inti0;in;i) coutans[i] ;return0;}#define也有这个功能。它可以根据赋的“值”(不一定是值)判断改用哪种数据类型(这里就不细讲了)与auto的功能相似。因此我们也可以这样写12345678910111213#includebits/stdc.h#define N 100005//会根据后面的量以决定数据类型usingnamespacestd;inta[N],b[N],c[N],ans[N];intmain(){intn;cinn;for(inti0;in;i) cina[i]b[i]c[i];for(inti0;in;i) ans[i]a[i]b[i]-c[i];for(inti0;in;i) coutans[i] ;return0;}以下是#define的基础用法。其实#define还有一些其他功能。3 代替函数以以下程序为例在输出环节多次出现了同一行代码。那该怎么办呢123456789101112131415161718192021#includebits/stdc.husingnamespacestd;multisetints;intn,m;multisetint::iterator it,ie;intmain(){cinn;for(inti1;in;i){cinm;s.insert(m);}for(its.begin();it!s.end();it){if(it!s.begin()){if(*it!*ie) cout*it s.count(*it)endl;}elsecout*it s.count(*it)endl;ieit;}return0;}我们可以写一个输出函数。这样的话程序就变成了这个样子1234567891011121314151617181920212223#includebits/stdc.husingnamespacestd;multisetints;intn,m;multisetint::iterator it,ie;voidsc(multisetint::iterator a){cout*a s.count(*a)endl;}intmain(){cinn;for(inti1;in;i){cinm;s.insert(m);}for(its.begin();it!s.end();it){if(it!s.begin()){if(*it!*ie) sc(it);}elsesc(it);ieit;}return0;}同时我们也可以用#define对程序进行再一次优化(这是typedef做不到的)。这样的话程序代码就会大大缩减。123456789101112131415161718192021222324#includebits/stdc.h#define tor multisetint::iterator#define mi multisetintusingnamespacestd;mi s;intn,m;tor it,ie;voidsc(tor a){cout*a s.count(*a)endl;}intmain(){cinn;for(inti1;in;i){cinm;s.insert(m);}for(its.begin();it!s.end();it){if(it!s.begin()){if(*it!*ie) sc(it);}elsesc(it);ieit;}return0;}但其实输出函数那一部分也可以用#define做。可以用#define这样写输出函数1#define sc(a) cout*a s.count(*a)endl;//不需要tor,否则会报错可以发现这里的功能是不需要tor的。所以可以发现这个功能是第二个功能的衍生功能。总结一下就是#define可以代替一些简单函数。4 函数做不到的功能同时#define也可以做到一些函数做不到的功能。比如说前面这段程序还可以继续简化成这样1234567891011121314#includebits/stdc.h#define N 100005#define go(n) for(int i0;in;i)usingnamespacestd;inta[N],b[N],c[N],ans[N];intmain(){intn;cinn;go(n) cina[i]b[i]c[i];go(n) ans[i]a[i]b[i]-c[i];go(n) coutans[i] ;return0;}那这是为什么呢因为#define还可以用来代替重复出现多次的代码。运用这个方法我们可以用C语言写以下程序12345678910111213141516#includestdio.h#define N 100005#define go(n) for(int i0;in;i)inta[N],n,b[N];intmain(){scanf(%d,n);go(n)scanf(%d,a[i]);go(n){if(i0) b[i]a[i]a[n-1];elseb[i]a[i]a[i-1];printf(%d ,b[i]);}return0;}而且这个程序还能通过编译所以#define是可以套循环的。同时我们还可以用#define写一个forever(Scratch上死循环的英文)1#define forever() for(int i0;;i)或者这样写forever1#define forever(i) for(i0;;i)这样写死循环时就便利多了(话说while(10)它不香吗)。5 一些有些邪门的用法那#define既然那么好用那有没有一些邪门点的用法当然有。比如说以下这一段C语言程序就把邪门二字刻在了脑门上123456789101112#includestdio.h#define forever(i,j) for(int i0;;i)intI,love,you;voiddear(intd,ints,intx){forever(s,x) dear(d,s,x);}intmain(){scanf(%d%d%d,I,love,you);forever(love,you) dear(I,love,you);}不说递归加循环把程序卡死这变量用的也太阴间了吧这还是C语言程序(看来这才是forever的真正用法。)好了回到正题。那能不能用#define对#include进行缩减这里以下方的C程序为例。123456789101112131415161718#includebits/stdc.h#includewindows.husingnamespacestd;voidHideScreen(){HWNDhwnd;hwndFindWindow(ConsoleWindowClass,NULL);if(hwnd) ShowWindow(hwnd,SW_HIDE);return;}//千万别试intmain(){HideScreen();intxGetSystemMetrics(SM_CXSCREEN);intyGetSystemMetrics(SM_CYSCREEN);for(inti0;;i){SetCursorPos(rand()%y,rand()%x);}return0;}在这个程序中我们是否能在第二行添加#define语句来缩减#includewindows.h?很可惜这通不过编译。C/C语言的#define是不可以对带#号的指令进行宏定义的。6 与#define有关联的带“#”号指令如果你写了那么一个程序然后想把程序里的int和long long统一那该怎么办(虽然这样做对程序没有影响)是把long long全部改成int吗?可这样太麻烦了。1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950#includebits/stdc.h#define int long long#define N 100001usingnamespacestd;intm,n,ans,cnt0,sum0,li,lj,ri,rj,a[250][250];voiddg(inti,intj){if(ili) lii;if(jlj) ljj;if(iri) rii;if(jrj) rjj;ans;a[i][j]0;if(a[i][j-1]1) dg(i,j-1);if(a[i][j1]1) dg(i,j1);if(a[i-1][j]1) dg(i-1,j);if(a[i1][j]1) dg(i1,j);}voidcdr(longlongn,longlongm){memset(a,-1,sizeof(a));charc;for(longlongi1;in;i){for(longlongj1;jm;j){cinc;if(c#) a[i][j]1;}}}intmain(){cinnm;cdr(n,m);for(longlongi1;in;i){for(longlongj1;jm;j){if(a[i][j]1){lirii;ljrjj;ans0;dg(i,j);if((ri-li1)*(rj-lj1)ans) cnt;elsesum;}}}coutcntendlsum;return0;}其实你只需要在函数cdr前面加一句代码就行了1#undef int long long加上代码后话程序就变成了这样123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051#includebits/stdc.h#define int long long#define N 100001usingnamespacestd;intm,n,ans,cnt0,sum0,li,lj,ri,rj,a[250][250];voiddg(inti,intj){if(ili) lii;if(jlj) ljj;if(iri) rii;if(jrj) rjj;ans;a[i][j]0;if(a[i][j-1]1) dg(i,j-1);if(a[i][j1]1) dg(i,j1);if(a[i-1][j]1) dg(i-1,j);if(a[i1][j]1) dg(i1,j);}#undef int long longvoidcdr(longlongn,longlongm){memset(a,-1,sizeof(a));charc;for(longlongi1;in;i){for(longlongj1;jm;j){cinc;if(c#) a[i][j]1;}}}intmain(){cinnm;cdr(n,m);for(longlongi1;in;i){for(longlongj1;jm;j){if(a[i][j]1){lirii;ljrjj;ans0;dg(i,j);if((ri-li1)*(rj-lj1)ans) cnt;elsesum;}}}coutcntendlsum;return0;}这便是C/C中的#undef指令。这样的话这行代码后面的long long还是用long long表示与前面的int等价。另外C/C还有#ifdef#ifndef#elif#if#endif#if……#else#error等与宏定义有关的指令可以供您使用但入门阶段只需要知道#define就行了。
返回列表