C语言是面向过程的,而C++是面向对象的
C和C++的区别:
C是一个结构化语言,它的重点在于算法和数据结构。C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到输出(或实现过程(事务)控制)。
C++,首要考虑的是如何构造一个对象模型,让这个模型能够契合与之对应的问题域,这样就可以通过获取对象的状态信息得到输出或实现过程(事务)控制。 所以C与C++的最大区别在于它们的用于解决问题的思想方法不一样。之所以说C++比C更先进,是因为“ 设计这个概念已经被融入到C++之中 ”。
小编推荐一个学C语言/C++的学习裙【 六九九,四七零,五九六 】,无论你是大牛还是小白,是想转行还是想入行都可以来了解一起进步一起学习!裙内有开发工具,很多干货和技术资料分享!
函数的调用规则多数情况下是不需要了解的。但是在跨语言和跨平台编程,比如DLL和COM编程时,就需要了解是怎么回事,因为这涉及到函数参数进出栈的顺序和清理工作。
例如:microsoft的vc默认的是__cdecl方式,而windows API则是__stdcall,如果用vc开发dll给其他语言用,则应该指定__stdcall方式。堆栈由谁清除这个很重要,如果是要写汇编函数给C调用,一定要小心堆栈的清除工作,如果是__cdecl方式的函数,则函数本身(如果不用汇编写)则不需要关心保存参数的堆栈的清除,但是如果是__stdcall的规则,一定要在函数退出(ret)前恢复堆栈。
调用约定(Calling Convention)是指在程序设计语言中为了实现函数调用而建立的一种协议。这种协议规定了该语言的函数中的参数传送方式、参数是否可变和由谁来处理堆栈等问题。不同的语言定义了不同的调用约定。
在C++中,为了允许操作符重载和函数重载,C++编译器往往按照某种规则改写每一个入口点的符号名,以便允许同一个名字(具有不同的参数类型或者是不同的作用域)有多个用法,而不会打破现有的基于C的链接器。这项技术通常被称为名称改编(Name Mangling)或者名称修饰(Name Decoration)。许多C++编译器厂商选择了自己的名称修饰方案。
因此,为了使其它语言编写的模块(如Visual Basic应用程序、Pascal或Fortran的应用程序等)可以调用C/C++编写的DLL的函数,必须使用正确的调用约定来导出函数,并且不要让编译器对要导出的函数进行任何名称修饰。
函数调用规则主要有以下几种:
1、__cdecl
__cdecl调用规则就是C调用规则。按从右至左的顺序压参数入栈,由调用者把参数弹出栈。切记:对于传送参数的内存栈是由调用者来维护的。返回值在EAX中因此,对于象printf这样变参数的函数必须用这种规则。编译器在编译的时候对这种调用规则的函数生成修饰名的饿时候,仅在输出函数名前加上一个下划线前缀,格式为_functionname。
int f(int a,int b);//不加修饰,默认__cdecl调用
int __cdecl f(int a,int b);//明确指出__cdecl调用。
示例程序:
1: #include
2:
3: int __cdecl f(int a,int b)
4: {
5: int c;
6: c = a + b;
7: return c;
8: }
汇编代码如下:注意最后一句ret,后面没有参数。
00401020 push ebp
00401021 mov ebp,esp
00401023 sub esp,44h
00401026 push ebx
00401027 push esi
00401028 push edi
00401029 lea edi,[ebp-44h]
0040102C mov ecx,11h
00401031 mov eax,0CCCCCCCCh
00401036 rep stos dword ptr [edi]
00401038 mov eax,dword ptr [ebp+8]
0040103B add eax,dword ptr [ebp+0Ch]
0040103E mov dword ptr [ebp-4],eax
00401041 mov eax,dword ptr [ebp-4]
00401044 pop edi
00401045 pop esi
00401046 pop ebx
00401047 mov esp,ebp
00401049 pop ebp
0040104A ret
***可变参数函数只能是__cdecl调用规则!***
2、__stdcall
__stdcall也是按从右至左的顺序压参数入栈,但是它是由被调用者把参数弹出栈。_stdcall是Pascal程序的缺省调用方式,通常用于Win32 Api中,切记:函数自己在退出时清空堆栈,返回值在EAX中。 __stdcall调用约定在输出函数名前加上一个下划线前缀,后面加上一个“@”符号和其参数的字节数,格式为_functionname@number。如函数int func(int a, double b)的修饰名是_func@12。
示例程序:
1: #include
2:
3: int __stdcall f(int a,int b)
4: {
5: int c;
6: c = a + b;
7: return c;
8: }
小编推荐一个学C语言/C++的学习裙【 六九九,四七零,五九六 】,无论你是大牛还是小白,是想转行还是想入行都可以来了解一起进步一起学习!裙内有开发工具,很多干货和技术资料分享!
汇编代码如下:注意最后一句ret 8!与__cdecl相比多了个参数8!
00401020 push ebp
00401021 mov ebp,esp
00401023 sub esp,44h
00401026 push ebx
00401027 push esi
00401028 push edi
00401029 lea edi,[ebp-44h]
0040102C mov ecx,11h
00401031 mov eax,0CCCCCCCCh
00401036 rep stos dword ptr [edi]
00401038 mov eax,dword ptr [ebp+8]
0040103B add eax,dword ptr [ebp+0Ch]
0040103E mov dword ptr [ebp-4],eax
00401041 mov eax,dword ptr [ebp-4]
00401044 pop edi
00401045 pop esi
00401046 pop ebx
00401047 mov esp,ebp
00401049 pop ebp
0040104A ret 8
3、__fastcall
__fastcall调用的主要特点就是快,因为它是通过寄存器来传送参数的(实际上,它用ECX和EDX传送前两个双字(DWORD)或更小的参数,剩下的参数仍旧自右向左压栈传送,被调用的函数在返回前清理传送参数的内存栈)。__fastcall调用约定在输出函数名前加上一个“@”符号,后面也是一个“@”符号和其参数的字节数,格式为@functionname@number。这个和__stdcall很象,唯一差别就是头两个参数通过寄存器传送。注意通过寄存器传送的两个参数是从左向右的,即第一个参数进ECX,第2个进EDX,其他参数是从右向左的入stack。返回仍然通过EAX..
示例程序:
1: #include
2:
3: int __stdcall f(int a,int b)
4: {
5: int c;
6: c = a + b;
7: return c;
8: }
小编推荐一个学C语言/C++的学习裙【 六九九,四七零,五九六 】,无论你是大牛还是小白,是想转行还是想入行都可以来了解一起进步一起学习!裙内有开发工具,很多干货和技术资料分享!
汇编代码如下,注意比较其与__stdcall和__cdecl在寄存器上的区别。
00401020 push ebp
00401021 mov ebp,esp
00401023 sub esp,4Ch
00401026 push ebx
00401027 push esi
00401028 push edi
00401029 push ecx
0040102A lea edi,[ebp-4Ch]
0040102D mov ecx,13h
00401032 mov eax,0CCCCCCCCh
00401037 rep stos dword ptr [edi]
00401039 pop ecx
0040103A mov dword ptr [ebp-8],edx
0040103D mov dword ptr [ebp-4],ecx
00401040 mov eax,dword ptr [ebp-4]
00401043 add eax,dword ptr [ebp-8]
00401046 mov dword ptr [ebp-0Ch],eax
00401049 mov eax,dword ptr [ebp-0Ch]
0040104C pop edi
0040104D pop esi
0040104E pop ebx
0040104F mov esp,ebp
00401051 pop
这些是C/C++能做的
服务器开发工程师、人工智能、云计算工程师、信息安全(黑客反黑客)、大数据 、数据平台、嵌入式工程师、流媒体服务器、数据控解、图像处理、音频视频开发工程师、游戏服务器、分布式系统、游戏辅助等
领取专属 10元无门槛券
私享最新 技术干货