网民的天上的动物 自我保护护措施有哪些

温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
如:if (string == 0 || string == 1)判断是否相等&一般建议写为:if (0 == string || 1 == string)2、C99标准 _Bool&_Bool a = 0;3、#define&#define ONE 1#define TWO ONE + ONE#define THREE ONE + TWO4、位运算&1 #include&stdio.h&&&int main(void)&{& & &unsigned char x = 0xe4,y;&& & & y = x && 2;&& & &printf("%x\n",y);& & &printf("%#x\n",y);& & &return 0;&}结果为 90 0x90 &左移表示在坐便去掉几位、然后在右边补0即可。5、putcharputchar(10) 和putchar(0x0a) 是一样、表述换行.具体可看ASCII码表。也可以写为printf("\n");6、#if 0 #endif 和#ifndef #endif前者表示预留重要代码调试位置后者表示条件编译7、goto 语句lp:if(i &=100)& & & & { & & &&& & & & & & & & sum = sum +& & & & & & & & i++;& & & & & & & && & & & } & & &&& & & & printf("%d",sum);8、while(day-- & 0) &表示趋近于0 但是不等于09、scanf("%[^\n]",ch); &表示取反,也就是 不包括\n.10、结构体空间(sizeof)大小等于总偏移量 除以 最后一个成员大小。如struct struct1{
};如下计算方法:&偏移量&补值&成员大小&0&0&11&3&4&8&0&18+1 /4需要补3 所以为9 + 3 = 12 &&故上述为12换一个.struct struct1{ char name[20];
char &sex[4];}&偏移量&补值&成员大小&0&0&2020&0&424&0&4故最后结果为24+4 /4。所以为2811、在C中、想同的变量 &局部会屏蔽全局变量。12、分清楚&取地址和取数据的关系(指针) 。13、存储区域。
Static全局
静态存储区
函数调用开始到结束
程序整个运行期间
定义变量的函数或复合语句
每次函数调用时候
编译时赋初值,只赋一次
自动赋初值0
注意局部变量和全局变量的区别.14、extern xx.表示在其它文件中使用这个变量.待续.......15、^ …… ^号在程序设计中有着多层意思。可以是shell中的“除了” 也可以是makefile中的$^ 所有不重复的依赖文件 还可以是vim中的行首当然也可以是C语言中的异或运算符号.simple example.冒泡排序swap(int a[],int b[]){ a ^= b ^= a ^=}表示交换。其实这里是指的两个值之间的异或运算.不进位的二进制计算。待续……
阅读(179)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
loftPermalink:'',
id:'fks_',
blogTitle:'C Bae (这样的C语言_again)',
blogAbstract:'1、在C语言中单等号和双等号有着本质的区别。如果用于比较一般用双等号,赋值一般用单等号。如:if (string == 0 || string == 1)判断是否相等&一般建议写为:if (0 == string || 1 == string)2、C99标准 _Bool&_Bool a = 0;3、#define&#define ONE 1#define TWO ONE + ONE#define THREE ONE + TWO4、位运算',
blogTag:'',
blogUrl:'blog/static/',
isPublished:1,
istop:false,
modifyTime:0,
publishTime:9,
permalink:'blog/static/',
commentCount:0,
mainCommentCount:0,
recommendCount:0,
bsrk:-100,
publisherId:0,
recomBlogHome:false,
currentRecomBlog:false,
attachmentsFileIds:[],
groupInfo:{},
friendstatus:'none',
followstatus:'unFollow',
pubSucc:'',
visitorProvince:'',
visitorCity:'',
visitorNewUser:false,
postAddInfo:{},
mset:'000',
remindgoodnightblog:false,
isBlackVisitor:false,
isShowYodaoAd:false,
hostIntro:'',
hmcon:'0',
selfRecomBlogCount:'0',
lofter_single:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}zhang12247 的BLOG
用户名:zhang12247
访问量:1284
注册日期:
阅读量:5863
阅读量:12276
阅读量:420527
阅读量:1108801
51CTO推荐博文
练习数字全排列时发现出现这种问题:#include &stdio.h&
#include &stdlib.h&
//#define swap(a,b) {a=a+b;b=a-b;a=a-b;}
#define swap(a,b) {tmp=a;a=b;b=}
int g_count=1;
int g_n=0;
void p(int *a,int size);
void print_result(int *a);
int main(int argc, char *argv[])
int array[]={1,2};
g_n=sizeof(array)/sizeof(int);
p(array,g_n);
system("PAUSE");
void print_result(int *a)
printf("count %d:",g_count++);
//printf("g_n=%d",g_n);
for(i=0;i&g_n;i++)
printf(" %d",a[i]);
printf("\n");
void p(int *a,int size)
if(size==1)
print_result(a);
int i,tmp=0;
for(i=0;i&i++)
//printf("before1:a%d=%d,a%d=%d\n",i,a[i],size-1,a[size-1]);
swap(a[i],a[size-1]);
//printf("before2:a%d=%d,a%d=%d\n",i,a[i],size-1,a[size-1]);
p(a,size-1);
swap(a[i],a[size-1]);
//printf("after:a%d=%d,a%d=%d\n",i,a[i],size-1,a[size-1]);
}以上代码实现的是数字全排列,但是使用define swap(a,b) {a=a+b;b=a-b;a=a-b;}和#define swap(a,b) {tmp=a;a=b;b=}得出的是不同的结果。难道是编译器的问题吗?编译器是dev c++的。前者结果是2,1和1,2。后者结果就是2,1和1,0了结论:调试后发现,当传入参数是同一个参数时,swap传入参数为(a[1],a[1])时,当执行define swap(a,b) {a=a+b;b=a-b;a=a-b;} 假设a[1]的值为2,则或许会认为执行第一步a=a+b时,a=4,b=2。但是调试后发觉由于传入参数是同一个变量,所以此时a=4时,b的值也同样变成了4.造成交换不成功。所以提醒,当涉及数组交换时,最好还是使用第二种比较稳妥些。因为或许在交换数组时出现,传入参数为同一个数组值。本文出自 “” 博客,请务必保留此出处
了这篇文章
类别:未分类┆阅读(0)┆评论(0)> C语言位运算总结位操作基础基本的位操作符有与、或、异或、取反、左移、右移这6种,它们的运算规则如下
C语言位运算总结位操作基础基本的位操作符有与、或、异或、取反、左移、右移这6种,它们的运算规则如下
发布时间: & &
浏览:2 & &
回复:0 & &
悬赏:0.0希赛币
C语言位运算总结
位操作基础
  基本的位操作符有与、或、异或、取反、左移、右移这6种,它们的运算规则如下所示:
  运算规则
  两个位都为1时,结果才为1
  两个位都为0时,结果才为0
  两个位相同为0,相异为1
  0变1,1变0
  各二进位全部左移若干位,高位丢弃,低位补0
  各二进位全部右移若干位,对无符号数,高位补0,有符号数,各编译器处理方法不一样,有的补符号位(算术右移),有的补0(逻辑右移)
  注意以下几点:
  在这6种操作符,只有~取反是单目操作符,其它5种都是双目操作符。
  位操作只能用于整形数据,其他类型进行位操作会被编译器报错。
  对于移位操作,在微软的VC6.0和VS2008编译器都是采取算术称位即算术移位操作,算术移位是相对于逻辑移位,它们在左移操作中都一样,低位补0即可,但在右移中逻辑移位的高位补0而算术移位的高位是补符号位。如下面代码会输出-4和3。
位操作应用
位运算的简单应用
  表达式
  位运算等价
  x+y
  (x|y)+(x&y)
  (x|~y)-(~x&y)
  (x|y)-(x&y)
  (x&~y)+y
  (~x|y)-~x
  (x-y|y-x)
  x-y|y-x
  (x-y)^((x^y)&((x-y)^x))
  (~x&y)|((~x|y)&(x-y)) //无符号x,y比较
  (~x|y)&((x^y)|~(y-x)) //无符号x,y比较
  只要根据最未位是0还是1来决定,为0就是偶数,为1就是奇数。因此可以用if (a & 1 == 0)代替if (a % 2 == 0)来判断a是不是偶数。可以得到如下代码:
bool&isEven(int&n)
&&&&&&&&return&
&&&&}&else&{
&&&&&&&&return&
不使用第三变量的两数交换
void&swap(int&&a,&int&&b)
  可以这样理解:
  1)a^=b 即a=(a^b);
  2)b^=a 即b=b^(a^b),由于^运算满足交换律,b^(a^b)=b^b^a。由于一个数和自己异或的结果为0并且任何数与0异或都会不变的,所以此时b被赋上了a的值。
  3)a^=b 就是a=a^b,由于前面二步可知a=(a^b),b=a,所以a=a^b即a=(a^b)^a。故a会被赋上b的值。
  再来个实例说明下以加深印象。int a = 13, b = 6;
  a的二进制为 13=8+4+1=1101(二进制)
  b的二进制为 6=4+2=110(二进制)
  第一步 a^=b a = 1101 ^ 110 = 1011;
  第二步 b^=a b = 110 ^ 1011 = 1101;即b=13
  第三步 a^=b a = 1011 ^ 1101 = 110;即a=5
  变换符号就是正数变成负数,负数变成正数。可以利用求补码的方法(按位取反+1)来 处理。
  如对于-11和11,可以通过下面的变换方法将-11变成11
  (二进制) –取反-& (二进制) –加1-& (二进制)
  同样可以这样的将11变成-11
  (二进制) –取反-& (二进制) –加1-& (二进制)
  可以得到如下代码:
int&changeSign(int&n)
&&&&return&~n
取绝对值
  对于任何数,与0异或都会保持不变,与-1即0xFFFFFFFF异或就相当于取反,因此,a与i异或后再减i(因为i为0或-1,所以减i即是要么加0要么加1)也可以得到绝对值因此可以得 到如下代码:
int&abs(int&n)
&&&&return&(n
^ (n $>$ 31))& - (n $>$ 31);
高低位互换
  给出一个32位的无符号整数。称这个二进制数的前16位为“高位”,后16位为“低位”。现在写一程序将它的高低位交换。例如,数0x1234ABCD用二进制表示为:
  将它的高低位进行交换,我们得到了一个新的二进制数:
  它即是0xABCD1234。
  这个问题用位操作解决起来非常方便,设x=0x1234ABCD由于x为无符号数,右移时会执行逻辑右移即高位补0,因此x右移16位将得到00 10 。而x左移8位将得到00 11 。可以发现只要将x$>$16与x$<$16这两个数相或就可以得到结果。代码如下
int&exchangeBits(unsigned&int&n)
&&&&return&(n
$>$ 16) | (n $<$ 16);
二进制逆序
  我们知道如何对字符串求逆序,现在要求计算二进制的逆序,如数34520用二进制表示为:00
  将它逆序,我们得到了一个新的二进制数:11
  它即是十进制的7009。
  回顾下字符串的逆序的方法,可以从字符串的首尾开始,依次交换两端的数据。在二进制逆序我们也可以用这种方法,但运用位操作的高低位交换来处理二进制逆序将会得到更简洁的方法。类&#20284;于归并排序的分组处理,可以通过下面4步得到32位数据的二进制逆序:
  第一步:每2位为一组,组内高低位交换
  00 00 00 00 00 00 00 00 10 00 01 10 11 01 10 00
  → 00 00 00 00 00 00 00 00 01 00 10 01 11 10 01 00
  第二步:每4位为一组,组内高低位交换
  → 00 10
  第三步:每8位为一组,组内高低位交换
  第四步:每16位为一组,组内高低位交换
  对第一步,可以依次取出每2位作一组,再组内高低位交换,这样有点麻烦,下面介绍一种非常有技巧的 方法。先分别取11000的奇数位和偶数位,空位以下划线表示。
  原 数 & 10
  奇数位 0_0_0_0_ 0_0_0_0_ 1_0_0_1_ 1_0_1_0_
  偶数位 _0_0_0_ 0 _0_0_0_ 0 _0_0_1_0 _1_1_0_0
  将下划线用0填充,可得
  原 数 & 10
  奇数位 10
  偶数位 00
  再将奇数位右移一位,偶数位左移一位,此时将这两个数据相与即可以达到奇偶位上数据交换的效果了。
  原 数 & & & & & 10
  奇数位右移 11
  偶数位左移 00
  相或得到 & &00
  可以看出,结果完全达到了奇偶位的数据交换,再来考虑代码的实现——
  取x的奇数位并将偶数位用0填充用代码实现就是x & 0xAAAAAAAA
  取x的偶数位并将奇数位用0填充用代码实现就是x & 0×
  因此,第一步就用代码实现就是:
  x = ((x & 0xAAAAAAAA) $>$ 1) | ((x & 0×) $<$ 1);
  类&#20284;可以得到如下代码:
int&revertBits(unsigned&int&n)
= ((n & 0xAAAAAAAA) $>$ 1 ) | ((n & 0x) $<$ 1);
= ((n & 0xCCCCCCCC) $>$ 2 ) | ((n & 0x) $<$ 2);
= ((n & 0xF0F0F0F0) $>$ 4 ) | ((n & 0x0F0F0F0F) $<$ 4);
= ((n & 0xFF00FF00) $>$ 8 ) | ((n & 0x00FF00FF) $<$ 8);
= ((n & 0xFFFF0000) $>$ 16 ) | ((n & 0x0000FFFF) $<$ 16);
&&&&return&n;
  32位整数前导零的个数
int&preZero(unsigned&int&n)
&&&&int&count
&&&&&&&&return(32);
&&&&if&((n
$>$ 16) == 0)
&&&&&&&&count
= count &#43; 16; n = n $<$ 16;
&&&&if&((n
$>$ 24) == 0)
&&&&&&&&count
= count &#43; 8; n = n $<$ 8;
&&&&if&((n
$>$ 28) == 0)
&&&&&&&&count
= count &#43; 4; n = n $<$ 4;
&&&&if&((n
$>$ 30) == 0)
&&&&&&&&count
= count &#43; 2; n = n $<$ 2;
&&&&if&((n
$>$ 31) == 0)
&&&&&&&&count
= count &#43; 1; n = n $<$ 1;
&&&&return&
二进制中1的个数
  方法1:
  考虑到n-1会把n的二进制表示中最低位的1置0并把其后的所有0置1,同时不改变此位置前的所有位,那么n&(n-1)即可消除这个最低位的1。这样便有了比顺序枚举所有位更快的算法:循环消除最低位的1,循环次数即所求1的个数。此算法的时间复杂度为O(n的二进制表示中的1的个数),最坏情况下的复杂度O(n的二进制表示的总位数)。
int&count1(unsigned&int&n)
&&&&int&count
&&&&while(n)
&= (n - 1);
&&&&&&&&count&#43;&#43;;
&&&&return&
  方法2:
  通过下面四步来计算其二进制中1的个数二进制中1的个数。
  第一步:每2位为一组,组内高低位相加
  00 00 00 00 00 00 00 00 10 00 01 10 11 01 10 00
  → 00 00 00 00 00 00 00 00 01 00 01 01 10 01 01 00
  第二步:每4位为一组,组内高低位相加
  → 00 10
  第三步:每8位为一组,组内高低位相加
  第四步:每16位为一组,组内高低位相加
  代码如下:
int&count1_2(unsigned&int&n)
= ((n & 0xAAAAAAAA) $>$ 1 ) &#43; (n & 0x);
= ((n & 0xCCCCCCCC) $>$ 2 ) &#43; (n & 0x);
= ((n & 0xF0F0F0F0) $>$ 4 ) &#43; (n & 0x0F0F0F0F);
= ((n & 0xFF00FF00) $>$ 8 ) &#43; (n & 0x00FF00FF);
= ((n & 0xFFFF0000) $>$ 16 ) &#43; (n & 0x0000FFFF);
&&&&return&n;
  参考资料
你可能还喜欢:
fixed()和setprecision()函数的用法C&#43;&#43;头文件大全“顶嵌杯”全国嵌入式系统C语言编程大赛(解题报告)Qt编程技巧 多个信号连接一个槽关于Qt 程序Release后不能找到输入点的问题解决Qt编程技巧 Qt 国际化C&#43;&#43;读取本地时间,用数码形式输出构造函数与析构函数研究Qt编程技巧 QTextBrowser显示文件内容Qt编程技巧 右键菜单
本问题标题:
本问题地址:
温馨提示:本问题已经关闭,不能解答。
暂无合适的专家
&&&&&&&&&&&&&&&
希赛网 版权所有 & &&C语言define用法详解
#define是C语言中提供的宏定义命令,其主要目的是为程序员在时提供一定的方便,并能在一定程度上提高程序的运行效率,但学生在学习时往往不能 理解该命令的本质,总是在此处产生一些困惑,在编程时误用该命令,使得程序的运行与预期的目的不一致,或者在读别人写的程序时,把运行结果理解错误,这对 C语言的学习很不利。
1 #define命令剖析
1.1 & #define的概念
#define命令是C语言中的一个宏定义命令,它用来将一个标识符定义为一个字符串,该标识符被称为宏名,被定义的字符串称为替换文本。
该命令有两种格式:一种是简单的宏定义,另一种是带参数的宏定义。
(1) & 简单的宏定义:
#define & &宏名&  &字符串&
& &例: & #define PI 3.1415926
(2) 带参数的宏定义
& &#define & &宏名& (&参数表&) & &宏体&
& &例: #define & A(x) x
一个标识符被宏定义后,该标识符便是一个宏名。这时,在程序中出现的是宏名,在该程序被编译前,先将宏名用被定义的字符串替换,这称为宏替换,替换后才进行编译,宏替换是简单的替换。
1.2 宏替换发生的时机
为了能够真正理解#define的作用,让我们来了解一下对C语言源程序的处理过程。当我们在一个集成的开发环境如Turbo C中将编写好的源程序进行编译时,实际经过了预处理、编译、汇编和连接几个过程,见图1。
源程序预处理器修改后的源程序编译器汇编程序汇编器可重定位的目标程序连接器可执行的目标程序图1 C语言的编译过程
其中预处理器产生编译器的输出,它实现以下的功能:
(1) & & 文件包含
可以把源程序中的#include 扩展为文件正文,即把包含的.h文件找到并展开到#include 所在处。
(2) & & 条件编译
预处理器根据#if和#ifdef等编译命令及其后的条件,将源程序中的某部分包含进来或排除在外,通常把排除在外的语句转换成空行。
(3) & & 宏展开
预处理器将源程序文件中出现的对宏的引用展开成相应的宏 定义,即本文所说的#define的功能,由预处理器来完成。
经过预处理器处理的源程序与之前的源程序有所有不同,在这个阶段所进行的工作只是纯粹的替换与展开,没有任何计算功能,所以在学习#define命令时只要能真正理解这一点,这样才不会对此命令引起误解并误用。
2 #define使用中的常见问题解析
2.1 简单宏定义使用中出现的问题
在简单宏定义的使用中,当替换文本所表示的字符串为一个表达式时,容易引起误解和误用。如下例:
例1 & #define & N & 2+2
void main()
& &int & a=N*N;
& &printf(&%d&,a);
(1) 出现问题:在此程序中存在着宏定义命令,宏N代表的字符串是2+2,在程序中有对宏N的使用,一般同学在读该程序时,容易产生的问题是先求解N为2+2=4,然后在程序中计算a时使用乘法,即N*N=4*4=16,其实该题的结果为8,为什么结果有这么大的偏差?
(2)问题解析:如1节所述,宏展开是在预处理阶段完成的,这个阶段把替换文本只是看作一个字符串,并不会有任何的计算发生,在展开时是在宏N出现的地方 只是简单地使用串2+2来代替N,并不会增添任何的符号,所以对该程序展开后的结果是a=2+2*2+2,计算后=8,这就是宏替换的实质,如何写程序才 能完成结果为16的运算呢?
(3)解决办法:将宏定义写成如下形式
#define & N & (2+2)
这样就可替换成(2+2)*(2+2)=16
2.2 带参数的宏定义出现的问题
在带参数的宏定义的使用中,极易引起误解。例如我们需要做个宏替换能求任何数的平方,这就需要使用参数,以便在程序中用实际参数来替换宏定义中的参数。一般学生容易写成如下形式:
#define & area(x) & x*x
这在使用中是很容易出现问题的,看如下的程序
void main()
int & y=area(2+2);
printf(&%d&,y);
按理说给的参数是2+2,所得的结果应该为4*4=16,但是错了,因为该程序的实际结果为8,仍然是没能遵循纯粹的简单替换的规则,又是先计算再替换 了,在这道程序里,2+2即为area宏中的参数,应该由它来替换宏定义中的x,即替换成2+2*2+2=8了。那如果遵循(1)中的解决办法,把2+2 括起来,即把宏体中的x括起来,是否可以呢?#define & area(x) (x)*(x),对于area(2+2),替换为(2+2)*(2+2)=16,可以解决,但是对于area(2+2)/area(2+2)又会怎么样 呢,有的学生一看到这道题马上给出结果,因为分子分母一样,又错了,还是忘了遵循先替换再计算的规则了,这道题替换后会变为 (2+2)*(2+2)/(2+2)*(2+2)即4*4/4*4按照乘除运算规则,结果为16/4*4=4*4=16,那应该怎么呢?解决方法是在整个 宏体上再加一个括号,即#define & area(x) ((x)*(x)),不要觉得这没必要,没有它,是不行的。
要想能够真正使用好宏定义,那么在读别人的程序时,一定要记住先将程序中对宏的使用全部替换成它所代表的字符串,不要自作主张地添加任何其他符号,完全展 开后再进行相应的计算,就不会写错运行结果。如果是自己编程使用宏替换,则在使用简单宏定义时,当字符串中不只一个符号时,加上括号表现出优先级,如果是 带参数的宏定义,则要给宏体中的每个参数加上括号,并在整个宏体上再加一个括号。看到这里,不禁要问,用宏定义这么麻烦,这么容易出错,可不可以摒弃它, 那让我们来看一下在C语言中用宏定义的好处吧。&
3 & 宏定义的优点
(1) & 方便程序的修改
使用简单宏定义可用宏代替一个在程序中经常使用的常量,这样在将该常量改变时,不用对整个程序进行修改,只修改宏定义的字符串即可,而且当常量比较长时, 我们可以用较短的有意义的标识符来写程序,这样更方便一些。我们所说的常量改变不是在程序运行期间改变,而是在编程期间的修改,举一个大家比较熟悉的例 子,圆周率&是在数学上常用的一个值,有时我们会用3.14来表示,有时也会用3.1415926等,这要看计算所需要的精度,如果我们编制的一个程序中 要多次使用它,那么需要确定一个数值,在本次运行中不改变,但也许后来发现程序所表现的精度有变化,需要改变它的值, 这就需要修改程序中所有的相关数值,这会给我们带来一定的不便,但如果使用宏定义,使用一个标识符来代替,则在修改时只修改宏定义即可,还可以减少输入 3.1415926这样长的数值多次的情况,我们可以如此定义 #define & pi & 3.1415926,既减少了输入又便于修改,何乐而不为呢?
(2) 提高程序的运行效率
使用带参数的宏定义可完成函数调用的功能,又能减少开 销,提高运行效率。正如C语言中所讲,函数的使用可以使程序更加模块化,便于组织,而且可重复利用,但在发生函数调用时,需要保留调用函数的现场,以便子 函数执行结束后能返回继续执行,同样在子函数执行完后要恢复调用函数的现场,这都需要一定的时间,如果子函数执行的操作比较多,这种转换时间开销可以忽 略,但如果子函数完成的功能比较少,甚至于只完成一点操作,如一个乘法语句的操作,则这部分转换开销就相对较大了,但使用带参数的宏定义就不会出现这个问 题,因为它是在预处理阶段即进行了宏展开,在执行时不需要转换,即在当地执行。宏定义可完成简单的操作,但复杂的操作还是要由函数调用来完成,而且宏定义 所占用的目标代码空间相对较大。所以在使用时要依据具体情况来决定是否使用宏定义。
形式参数不能用带引号的字符串替换。
但是,如果在替换文本中,参数名以#作为前缀则结果将被扩展为 由 实际参数 替换 此实际参数的带引号的字符串。
例如,可以将它与字符串连接运算结合起来编写一个调试打印宏:
#define dprint(expr) printf(#expr & = %\n&,expr)
使用语句 dprint(x/y);
调用宏时,该宏将被扩展为:printf(&x/y&& = %\n&,x/y);
其中的字符串被连接起来了,这样便等价于printf(&x/y = %\n&,x/y);
在实际参数中,每个双引号 & 将被替换为 \& ;反斜杠\将被替换为\\,因此替换后的字符串是合法的字符串常量。
预处理运算符 ## 为宏扩展提供了一种连接实际参数的手段。如果替换文本中的参数与 ## 相邻,则该参数将被实际参数替换,##与前后的空白符将被删除,并对替换后的结果重新扫描。
例如,下面定义的宏paste用于连接两个参数
#define paste(front, back) front ## back
因此,宏调用past(name,1)的结果将建立记号name1.
中没有swap这个函数,C语言不支持重载,也没有模版的概念,所以对于每一种类型,都要写出相应的swap,如
intSwap & (int & *, & int & *); &&
longSwap & (long & *, & long & *); &&
stringSwap & (char & *, & char & *); &
宏定义swap(t,x,y)以交换t类型的两个参数(要使用程序块结构)。
程序如下:
#include &iostream.h&
#define SWAP(t,x,y) \&
t temp = *y;\&
*y = *x;\&
int a = 10, b = 5;&
SWAP(int,&a,&b)&
cout && a && endl && b&&&
用\换行,\的意思是說把下一行看作和這行是同一行.換行必須要反斜杠,而且\後面直接回車,不能有空格}

我要回帖

更多关于 有关自我保护的谚语 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信