网站建设资讯

NEWS

网站建设资讯

c语言中宏和函数 c语言宏的概念

请问C语言中带参数的宏和函数的比较

宏是用于编译器处理的,他在程序编译时,会在对应位置展开成代码。。,这就相当于你在告诉编译器,我想在这个位置加一些代码,代码的内容已在宏中定义,请编译器自己支找。。。,也就是说程序在运行时,早已变成了对应位置上的代码,此时已没有宏的概念了。。。。

目前创新互联已为近千家的企业提供了网站建设、域名、网页空间、网站托管运营、企业网站设计、浑南网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。

而函数则是运行时,调用。他不会在编译时,在对应位置上加上函数代码,只是加上一个函数入口指针。。。从这个入口去运行一段代码。。。运行完了之后回到当前位置继续执行。。。。

可以简单的认为,宏是在编译时上起作用,而函数是运行时起作用。。。

宏和函数的区别以及C语言的编译链接过程

宏在编译之前,需要进行预处理,将宏直接提换成宏定义的代码,是直接替换,也就是说,在预处理之后,你再看代码,发现宏定义已经被替换过来了,你看到是你定义之后的那一串代码。

而函数,在编译之后,有一系列调用函数的过程,比如,传参,压栈等,这部分是编译器所做的。

C 语言编译链接过程:

test.c(原始代码) -- 预处理 -- test.i(经过预处理的)-- 编译 -- test.s(汇编代码)-- 汇编 -- test.o(目标文件,其实这部分已经是单个文件的完整二进制文件了,只是还不能执行,如果不懂这句话,可以再问我,其实这部分知识,平时也很少遇到) -- 链接 -- test (可执行文件,比如一个程序由3个代码文件共同生成,那么就会有3个.o格式目标文件,链接是把多个目标文件真正的联系在一起,比如a.o 中使用了 b.o中的一个函数,那么它们两个之间的地址是如何确定的(同理,可引申到使用函数库的问题,使用printf函数,也是需要链接器进行确定printf函数地址,才能知道如何调用。)这个就是链接器的作用)

我想知道c语言里面怎么区分函数与宏

在C及C++语言中允许用一个标识符来表示一个字符串,称为宏,该字符串可以是常数、表达式、格式串等。在编译预处理时,对程序中所有出现的“宏名”,都用宏定义中的字符串去代换,这称为“宏代换”或“宏展开”。宏定义是由源程序中的宏定义命令完成的。宏代换是由预处理程序自动完成的。若字符串是表达式,我们称之为函数式宏定义,那函数式宏定义与普通函数有什么区别呢?我们以下面两行代码为例,展开描述:

函数式宏定义:#define MAX(a,b) ((a)(b)?(a):(b))

普通函数 : MAX(a,b) { return ab?a:b;}

(1)函数式宏定义的参数没有类型,预处理器只负责做形式上的替换,而不做参数类型检查,所以传参时要格外小心。

(2)调用真正函数的代码和调用函数式宏定义的代码编译生成的指令不同。

如果MAX是个普通函数,那么它的函数体return a b ? a : b; 要编译生成指令,代码中出现的每次调用也要编译生成传参指令和call指令。而如果MAX是个函数式宏定义,这个宏定义本身倒不必编译生成指令,但是代码中出现的每次调用编译生成的指令都相当于一个函数体,而不是简单的几条传参指令和call指令。所以,使用函数式宏定义编译生成的目标文件会比较大。

(3)函数式宏定义要注意格式,尤其是括号。

如果上面的函数式宏定义写成 #define MAX(a, b) (ab?a:b),省去内层括号,则宏展开就成了k = (i0x0fj0x0f?i0x0f:j0x0f),运算的优先级就错了。同样道理,这个宏定义的外层括号也是不能省的。若函数中是宏替换为 ++MAX(a,b),则宏展开就成了 ++(a)(b)?(a):(b),运算优先级也是错了。

(4)若函数参数为表达式,则普通函数的调用与函数式宏定义的替换过程是不一样的。

普通函数调用时先求实参表达式的值再传给形参,如果实参表达式有Side Effect,那么这些SideEffect只发生一次。例如MAX(++a, ++b),如果MAX是普通函数,a和b只增加一次。但如果MAX函数式宏定义,则要展开成k = ((++a)(++b)?(++a):(++b)),a和b就不一定是增加一次还是两次了。所以若参数是表达式,替换函数式宏定义时一定要仔细看好。

(5)函数式宏定义往往会导致较低的代码执行效率。

看下面一段代码:

int a[]={9,3,5,2,1,0,8,7,6,4};

int max(n)

{

return n==0?a[0]:MAX(a[n],max(n-1));

}

int main()

{

max(9);

return 0;

}

若是普通函数,则通过递归,可取的最大值,时间复杂度为O(n)。但若是函数式宏定义,则宏展开为( a[n]max(n-1)?a[n]:max(n-1) ),其中max(n-1)被调用了两遍,这样依此递归下去,时间复杂度会很高。

尽管函数式宏定义和普通函数相比有很多缺点,但只要小心使用还是会显著提高代码的执行效率,毕竟省去了分配和释放栈帧、传参、传返回值等一系列工作,因此那些简短并且被频繁调用的函数经常用函数式宏定义来代替实现。


分享标题:c语言中宏和函数 c语言宏的概念
浏览地址:http://cdweb.net/article/doiphjd.html