“_cdecl”和“__cdecl”的区别是什么?

“_cdecl”和“__cdecl”的区别是什么?,第1张

1、_cdecl c调用约定, 按从右至左的顺序压参数入栈,由调用者把参数d出栈。对于传送参数的内存栈是由调用者来维护的(正因为如此,实现可变参数的函数只能使用该调用约定)。

另外,在函数名修饰约定方面也有所不同。 _cdecl是C和C++程序的缺省调用方式。每一个调用它的函数都包含清空堆栈的代码,所以产生的可执行文件大小会比调用_stdcall函数的大。函数采用从右到左的压栈方式。VC将函数编译后会在函数名前面加上下划线前缀,是MFC缺省调用约定。

2、__cdecl是C/C++和MFC程序默认使用的调用约定。采用__cdecl约定时,函数参数按照从右到左的顺序入栈,并且由调用函数者把参数d出栈以清理堆栈。

因此,实现可变参数的函数只能使用该调用约定。由于每一个使用__cdecl约定的函数都要包含清理堆栈的代码,所以产生的可执行文件大小会比较大。__cdecl可以写成_cdecl。

所谓的cdecl就是有关C语言函数参数入栈顺序的规范:

__cdecl 是C Declaration的缩写(declaration,声明),表示C语言默认的函数调用方法:所有参数从右到左依次入栈,这些参数由调用者清除,称为手动清栈。被调用函数不会要求调用者传递多少参数,调用者传递过多或者过少的参数,甚至完全不同的参数都不会产生编译阶段的错误。

C语言函数的参数入栈顺序是从右到左,而Pascal语言正好相反,从左至右。

如果满意,欢迎采纳,谢谢

如有疑问,欢迎追问

__cdecl一般不是让你直接用的,而是给编译器用的。这种情况最常见的一个例子就是__cplusplus

有时候你会在不同的C语言编译器的头文件里面看到类似__CDECL的标识符,这些大写的标识符仔细找,都可以在系统的头文件里面找到定义,有可能定义某个系统预定义的标识符,更可能定义成空的,定义成空的时候,在预编辑的过程中就删除了。

回到你的问题,首先说明,现在比较成熟的编译器都不允许你现在这种用法,而是要求必须有正确的函数原型。完全不同的参数都不会产生编译阶段的错误的意思也不是你理解的样子。你可以考虑把两个函数写到两个文件中试试。比如像这样:

F1.C

#include

<stdio.h>

void

__cdecl

PRINTF(int

x,

int

y){

printf("asd\n")}

需要说明的是加不加__cdecl都一样,C语言不加也按__cdecl方式编译。

F2.C

int

main(

void

)

{

PRINTF()

return

0

}

编译时会报警告,找不到PRINTF的原型,但运行是正常的。实际上你可以给PRINTF传递任意参数,比如PRINTF(0,1,2,3)都可以正常运行。这是因为调用PRINTF时是调用者清栈。

与调用者清栈相对应的是使用者清栈,PASCAL语言就是使用者清栈,而C语言是调用者清栈。


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/yw/7952103.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-11
下一篇 2023-04-11

发表评论

登录后才能评论

评论列表(0条)

保存