# \_\_cdecl

`__cdecl`（C Declaration）是C语言中的一种调用约定，主要特点如下：

#### 1. 堆栈清理

* 在`__cdecl`调用约定中，函数调用后，调用者负责清理堆栈。这意味着函数返回后，调用者需要手动调整堆栈指针，移除函数参数。

#### 2. 支持可变参数

* `__cdecl`可以用于支持可变参数的函数，例如`printf`。这意味着你可以传递不同数量和类型的参数。

#### 3. 参数传递顺序

* 函数参数从右到左入栈。例如，调用`foo(1, 2)`时，2首先入栈，然后是1。

#### 4. 名字修饰

* 在使用`__cdecl`时，编译器不会对函数名称进行修饰。这使得在链接时，可以直接使用函数名，而无需考虑名称重载的问题。

#### 5. 性能

* 由于调用者需要清理堆栈，`__cdecl`在性能上通常不如`__stdcall`高效，尤其是在参数较多的情况下。

#### 使用场景

* `__cdecl`常用于C和C++的标准库函数，以及不确定参数数量的函数。它在多种平台（如Windows和Linux）上被广泛支持。

#### 示例代码

```c
#include <stdio.h>

void __cdecl myFunction(int a, int b) {
    printf("a: %d, b: %d\n", a, b);
}

int main() {
    myFunction(10, 20);
    return 0;
}
```

#### <mark style="color:red;">为什么\_\_cdecl在性能上通常不如\_\_stdcall高效？</mark>

`__cdecl`在性能上通常不如`__stdcall`高效，主要是因为堆栈清理的责任不同。由于在`__cdecl`中，调用者负责清理堆栈，这意味着在每次函数调用后都需要额外的指令来调整堆栈指针。而在`__stdcall`中，由于被调用者清理堆栈，调用者的代码更简洁，减少了开销。此外，`__stdcall`在处理固定数量参数时，可以优化代码，从而提高执行效率。这种差异在频繁调用的函数中特别明显。

#### <mark style="color:red;">\_\_cdecl和\_\_stdcall的关系与区别</mark>

`__cdecl`和`__stdcall`都是调用约定，定义了函数参数如何传递以及如何清理堆栈。主要区别在于：

1. **堆栈清理**：`__cdecl`由调用者负责清理堆栈，而`__stdcall`由被调用者负责清理。
2. **参数传递顺序**：两者都从右到左传递参数，但`__stdcall`的函数名在编译时会被修饰，这使得它在链接时更易于管理。
3. **名称修饰方式**

* `__cdecl`：在编译后的函数名前会加上一个下划线。例如，函数`int add(int a, int b)`在编译后可能会被修饰为`_add`。
* `__stdcall`：在编译后的函数名前会加上一个下划线，后面加上`@`符号，再加上参数的字节数。例如，`int add(int a, int b)`可能会被修饰为`_add@8`。

一般来说，`__cdecl`支持可变参数，而`__stdcall`则通常用于WinAPI等固定参数的函数。
