zoukankan      html  css  js  c++  java
  • 【转】nginx中的ngx_cdecl

    http://blog.csdn.net/midion9/article/details/50605337 

    看nginx的代码时,发现有些函数返回值之后,还有一个ngx_cdecl关键字,如:

     
    1
    2
    3
    4
    5
    6
    7
    intngx_cdecl
    main(intargc, char*const*argv)
    {
        ngx_int_t         i;
        ngx_log_t        *log;
        ngx_cycle_t      *cycle, init_cycle;
        ngx_core_conf_t  *ccf;

    查看其定义处发现竟然是个空:

     
    1
    #define ngx_cdecl

    那么这个宏的作用是什么呢?如果了解函数调用的规则,则对这个宏基本上就能理解了:

    在C语言中,假设我们有这样的一个函数:int function(int a,int b),调用时只要用result = function(1,2)这样的方式就可以使用这个函数。但是,当高级语言被编译成计算机可以识别的机器码时,有一个问题就凸现出来:在CPU中,计算机没有办法知道一个函数调用需要多少个、什么样的参数,也没有硬件可以保存这些参数。也就是说,计算机不知道怎么给这个函数传递参数,传递参数的工作必须由函数调用者和函数本身来协调。为此,计算机提供了一种被称为栈的数据结构来支持参数传递。不同CPU,不同编译器的堆栈布局、函数调用方法都可能不同,但堆栈的基本概念是一样的。

    函数调用约定包括传递参数的顺序,谁负责清理参数占用的堆栈等,例如 :

    调用方法 参数传递顺序 谁负责清理参数占用的堆栈
    __pascal 从左到右 调用者
    __stdcall 从右到左 被调函数
    __cdecl 从右到左 调用者

    调用函数的代码和被调函数必须采用相同的函数的调用约定,程序才能正常运行。
    如前表所示,__cdecl和__stdcall的区别是:__cdecl是调用者清理参数占用的堆栈,__stdcall是被调函数清理参数占用的堆栈。假设函数A是__stdcall,函数B调用函数A。你必须通过函数声明告诉编译器,函数A是__stdcall。编译器自然会产生正确的调用代码。如果函数A是__stdcall。但在引用函数A的地方,你却告诉编译器,函数A是__cdecl方式,编译器产生__cdecl方式的代码,与函数A的调用约定不一致,就会发生错误。

    由于__stdcall的被调函数在编译时就必须知道传入参数的准确数目(被调函数要清理堆栈),所以不能支持变参数函数,例如printf。而且如果调用者使用了不正确的参数数目,会导致堆栈错误。

    因此,nginx中使用这个宏是为了跨平台支持,方便调整函数调用方式。在遇到问题时,可以修改上面的定义为:

     
    1
    #define ngx_cdecl stdcall
  • 相关阅读:
    netstat 命令查看本机网络连接情况
    代替readonly
    Windows 性能监视器工具perfmon
    IE地址栏显示网站图标
    git log
    git 远程仓库管理
    git branch
    linux 安装p7zip 支持rar
    git使用教程(二) 基础
    centos 安装chrome
  • 原文地址:https://www.cnblogs.com/xuyuan77/p/5918263.html
Copyright © 2011-2022 走看看