张德长

导航

参数传递和命名约定 Argument Passing and Naming Conventions

Argument Passing and Naming Conventions

参数传递和命名约定

Microsoft Specific

官方详解可见:https://msdn.microsoft.com/en-us/library/984x0h58(v=vs.120).aspx

The Visual C++ compilers allow you to specify conventions for passing arguments and return values between functions and callers. Not all conventions are available on all supported platforms, and some conventions use platform-specific implementations. In most cases, keywords or compiler switches that specify an unsupported convention on a particular platform are ignored, and the platform default convention is used.

Visual C++编译器允许您指定在函数和调用者之间传递参数和返回值的约定。并不是所有的约定都在所有支持的平台上可用,而且有些约定使用特定于平台的实现。在大多数情况下,在特定平台上指定不受支持的约定的关键字或编译器开关将被忽略,并使用平台默认约定。

On x86 plaftorms, all arguments are widened to 32 bits when they are passed. Return values are also widened to 32 bits and returned in the EAX register, except for 8-byte structures, which are returned in the EDX:EAX register pair. Larger structures are returned in the EAX register as pointers to hidden return structures. Parameters are pushed onto the stack from right to left. Structures that are not PODs will not be returned in registers.

The compiler generates prolog and epilog code to save and restore the ESI, EDI, EBX, and EBP registers, if they are used in the function.

编译器生成序言和尾声代码,以保存和恢复ESI、EDI、EBX和EBP寄存器,如果它们在函数中使用的话。

 Note

When a struct, union, or class is returned from a function by value, all definitions of the type need to be the same, else the program may fail at runtime.

当从函数按值返回结构、联合或类时,该类型的所有定义都需要相同,否则程序可能在运行时失败。

For information on how to define your own function prolog and epilog code, see Naked Function Calls.

有关如何定义您自己的函数序言和尾声代码的信息,请参阅函数调用。

For information about the default calling conventions in code that targets x64 platforms, see Overview of x64 Calling Conventions. For information about calling convention issues in code that targets ARM platforms, see Common Visual C++ ARM Migration Issues.

有关针对x64平台的代码中的默认调用约定的信息,请参见x64调用约定的概述。有关在针对ARM平台的代码中调用约定问题的信息,请参见常见的Visual C++ ARM迁移问题

Visual C/C++编译器支持以下调用约定。

The following calling conventions are supported by the Visual C/C++ compiler.

Keyword

关键词

Stack cleanup

清理堆栈??

Parameter passing 参数如何传递??

__cdecl

Caller

调用者负责清栈

Pushes parameters on the stack, in reverse order (right to left)

将参数反向入栈(从右到左)

__clrcall

n/a无人清栈

Load parameters onto CLR expression stack in order (left to right).

正向加载参数(从左到右)

__stdcall

Callee

被调者负责清栈

Pushes parameters on the stack, in reverse order (right to left)

将参数反向入栈(从右到左)

__fastcall

Stored in registers, then pushed on stack

参数先存储在寄存器,然后入栈

__thiscall

Pushed on stack; this pointer stored in ECX

参数入栈,而this指针存储在ECX寄存器

__vectorcall

Stored in registers, then pushed on stack in reverse order (right to left)

参数先存储在寄存器,然后反向入栈(从右到左)

For related information, see Obsolete Calling Conventions.

Convention英 [kənˈvenʃ(ə)n]  美 [kənˈvenʃ(ə)n]

  1. 习俗,惯例;大会,集会;公约,协定;(文学、艺术上的)传统手法,传统风格;

会议 大会 公约

Covenant英 [ˈkʌvənənt]  美 [ˈkʌvənənt]

  1. 盟约,契约;协议,盖印合同(尤指向慈善机构定期捐款);(上帝与人所立的)约
  2. 立约,立约同意;通过立约定期(给慈善机构等)捐(款)

异形:契约 Alien: Covenant

(1)简单的宏定义:

宏定义:#define <宏名>  <字符串>

宏展开:用字符串替换所有宏名

例: #define PI 3.1415926

(2) 带参数的宏定义

#define <宏名> (<参数表>) <宏体>

例: #define A(x) x

宏替换

编译预处理是实现以下功能:

(1)文件包含

可以把源程序中的#include 扩展为文件正文,即把包含的.h文件找到并展开到#include 所在处。

(2)条件编译

预处理器根据#if和#ifdef等编译命令及其后的条件,将源程序中的某部分包含进来或排除在外,通常把排除在外的语句转换成空行。

(3)宏展开

预处理器将源程序文件中出现的对宏的引用展开成相应的宏 定义,即本文所说的#define的功能,由预处理器来完成。

 

部分示例代码

// Definitions of calling conventions used code sometimes compiled as managed
#if defined _M_CEE_PURE || defined MRTDLL
    #define __CLRCALL_OR_CDECL __clrcall
    #define __CLR_OR_THIS_CALL __clrcall
#else
    #define __CLRCALL_OR_CDECL __cdecl
    #define __CLR_OR_THIS_CALL
#endif




template <class _Elem, class _Traits>
class basic_ostream : virtual public basic_ios<_Elem, _Traits> { // control insertions into a stream buffer
public:
    using _Myios = basic_ios<_Elem, _Traits>;
    using _Mysb  = basic_streambuf<_Elem, _Traits>;
    using _Iter  = ostreambuf_iterator<_Elem, _Traits>;
    using _Nput  = num_put<_Elem, _Iter>;

    explicit __CLR_OR_THIS_CALL basic_ostream(basic_streambuf<_Elem, _Traits>* _Strbuf, bool _Isstd = false) {
        _Myios::init(_Strbuf, _Isstd);
    }

    __CLR_OR_THIS_CALL basic_ostream(_Uninitialized, bool _Addit = true) {
        if (_Addit) {
            this->_Addstd(this); // suppress for basic_iostream
        }
    }

protected:
    __CLR_OR_THIS_CALL basic_ostream(basic_ostream&& _Right) {
        _Myios::init();
        _Myios::move(_STD move(_Right));
    }

 

posted on 2022-12-08 15:33  张德长  阅读(23)  评论(0编辑  收藏  举报