_cdecl、_stdcall和_fastcall的区别

2023-11-12

概述

在windows开发环境中有三种觉的调用协议,分别为

  • _cdecl C调用
  • _stdcall 标准调用
  • _fastcall 快速调用
    三种调用方式有参数传递和栈帧恢复的方式有所不同,本文在结合汇编代码简要说明一下有三种调用方式的区别。

环境

  • windows xp sp3
  • vc6.0
    在VC中可以使用_cdecl、_stdcall、_fastcall来指定函数的调用方式,默认为_cdecl

_cdecl

_cdecl 使用的栈来传递参数,从右向左将参数入栈,需要调用者要恢复栈
下面在vc环境中的看一下_cdecl的汇编代码
在vc6.0 新建一个控制台空工程
在VC6.0中新建空的控制台工程
新建一个简单的C程序,其中add函数的调用方式显式的指定为_cdecl

_cdecl int add(int a, int b, int c, int d)
{
	int local1;
	int local2 = 0;
	int sum = 0;
	sum = a + b + c + d;
	return sum;
}

int main()
{
	int local1;
	int local2 = 0;
	int sum = 0;
	sum = add(1,2,3,4);
	return 0;
}

在 add的调用处设置断点,编译生成后的运行显示出反汇编窗口
设置断点显示反汇编视图
main函数的汇编

--- c:\program files\microsoft visual studio\myprojects\1\1.cpp  --------------------------------------------------------------------------------------------------------------
10:
11:   int main()
12:   { 保存现场
00401070 55                   push        ebp
00401071 8B EC                mov         ebp,esp
00401073 83 EC 4C             sub         esp,4Ch
00401076 53                   push        ebx
00401077 56                   push        esi
00401078 57                   push        edi
00401079 8D 7D B4             lea         edi,[ebp-4Ch] ;在栈上分别局部变量空间
0040107C B9 13 00 00 00       mov         ecx,13h
00401081 B8 CC CC CC CC       mov         eax,0CCCCCCCCh   ;写入int 3
00401086 F3 AB                rep stos    dword ptr [edi]
13:       int local1;   //局部变量local1在 ebp-4 处
14:       int local2 = 0;  //局部变量local2在 ebp-8 处
00401088 C7 45 F8 00 00 00 00 mov         dword ptr [ebp-8],0
15:       int sum = 0; //局部变量sum中 ebp-12 处
0040108F C7 45 F4 00 00 00 00 mov         dword ptr [ebp-0Ch],0
16:       sum = add(1,2,3,4); //注意_cdecl的传参方式,从右向左压栈的方式传参
00401096 6A 04                push        4
00401098 6A 03                push        3
0040109A 6A 02                push        2
0040109C 6A 01                push        1
0040109E E8 62 FF FF FF       call        @ILT+0(add) (00401005)  ;call指令 将函数的返回地址(下一行指令地址004010A3)压入栈,跳转到00401005 E9 16 00 00 00        jmp         add (00401020)
004010A3 83 C4 10             add         esp,10h  ;调用完成后,恢复栈帧 esp + 4*4 这是参数占用的栈空间
004010A6 89 45 F4             mov         dword ptr [ebp-0Ch],eax ;将eax的值赋值给sum
17:       return 0;
004010A9 33 C0                xor         eax,eax eax=0
18:   }  恢复现场
004010AB 5F                   pop         edi
004010AC 5E                   pop         esi
004010AD 5B                   pop         ebx
004010AE 83 C4 4C             add         esp,4Ch
004010B1 3B EC                cmp         ebp,esp
004010B3 E8 18 00 00 00       call        __chkesp (004010d0)
004010B8 8B E5                mov         esp,ebp
004010BA 5D                   pop         ebp
004010BB C3                   ret
--- No source file  -----------------------------------------------------------------------------------------------------------------------------------------------------------

add函数的反汇编代码

--- c:\program files\microsoft visual studio\myprojects\1\1.cpp  ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1:
2:    _cdecl int add(int a, int b, int c, int d)
3:    { //保存现场 此时 栈项保存着返回地址
00401020 55                   push        ebp ;保存ebp
00401021 8B EC                mov         ebp,esp ;
00401023 83 EC 4C             sub         esp,4Ch ;扩展栈空间,用来存储局部变量 76个字节
00401026 53                   push        ebx
00401027 56                   push        esi
00401028 57                   push        edi
00401029 8D 7D B4             lea         edi,[ebp-4Ch] ;在局部变量的存储空间中写入int 3
0040102C B9 13 00 00 00       mov         ecx,13h ;13h=19
00401031 B8 CC CC CC CC       mov         eax,0CCCCCCCCh
00401036 F3 AB                rep stos    dword ptr [edi]
4:        int local1; //存储在ebp-4
5:        int local2 = 0; //存储在ebp-8
00401038 C7 45 F8 00 00 00 00 mov         dword ptr [ebp-8],0
6:        int sum = 0; //存储在ebp-12 处
0040103F C7 45 F4 00 00 00 00 mov         dword ptr [ebp-0Ch],0
7:        sum = a + b + c + d;
00401046 8B 45 08             mov         eax,dword ptr [ebp+8]
00401049 03 45 0C             add         eax,dword ptr [ebp+0Ch]
0040104C 03 45 10             add         eax,dword ptr [ebp+10h]
0040104F 03 45 14             add         eax,dword ptr [ebp+14h]
00401052 89 45 F4             mov         dword ptr [ebp-0Ch],eax
8:        return sum;
00401055 8B 45 F4             mov         eax,dword ptr [ebp-0Ch] ;将sum的值给eax,eax用来保存函数的返回值
9:    } //恢复现场
00401058 5F                   pop         edi
00401059 5E                   pop         esi
0040105A 5B                   pop         ebx
0040105B 8B E5                mov         esp,ebp
0040105D 5D                   pop         ebp
0040105E C3                   ret ; 从栈项弹出返回地址,跳转到返回地址处
--- No source file  ------------------------------------------------------

stdcall

stdcall 也使用栈从右至左来传递参数,在函数内部恢复栈帧 windows api一般采用这个方式
在上面的代码修改为如下


_stdcall int add(int a, int b, int c, int d)
{
	int local1;
	int local2 = 0;
	int sum = 0;
	sum = a + b + c + d;
	return sum;
}

int main()
{
	int local1;
	int local2 = 0;
	int sum = 0;
	sum = add(1,2,3,4);
	return 0;
}

汇编代码为

--- C:\Program Files\Microsoft Visual Studio\MyProjects\1\1.cpp  ------------------------
1:
2:    _stdcall int add(int a, int b, int c, int d)
3:    {
00401020 55                   push        ebp
00401021 8B EC                mov         ebp,esp
00401023 83 EC 4C             sub         esp,4Ch
00401026 53                   push        ebx
00401027 56                   push        esi
00401028 57                   push        edi
00401029 8D 7D B4             lea         edi,[ebp-4Ch]
0040102C B9 13 00 00 00       mov         ecx,13h
00401031 B8 CC CC CC CC       mov         eax,0CCCCCCCCh
00401036 F3 AB                rep stos    dword ptr [edi]
4:        int local1;
5:        int local2 = 0;
00401038 C7 45 F8 00 00 00 00 mov         dword ptr [ebp-8],0
6:        int sum = 0;
0040103F C7 45 F4 00 00 00 00 mov         dword ptr [ebp-0Ch],0
7:        sum = a + b + c + d;
00401046 8B 45 08             mov         eax,dword ptr [ebp+8]
00401049 03 45 0C             add         eax,dword ptr [ebp+0Ch]
0040104C 03 45 10             add         eax,dword ptr [ebp+10h]
0040104F 03 45 14             add         eax,dword ptr [ebp+14h]
00401052 89 45 F4             mov         dword ptr [ebp-0Ch],eax
8:        return sum;
00401055 8B 45 F4             mov         eax,dword ptr [ebp-0Ch]
9:    }
00401058 5F                   pop         edi
00401059 5E                   pop         esi
0040105A 5B                   pop         ebx
0040105B 8B E5                mov         esp,ebp
0040105D 5D                   pop         ebp
0040105E C2 10 00             ret         10h ;ret n指令将 返回地址(004010A3) 从栈顶弹出,再将esp+4*4 跳转到返回地址 在函数内部恢复栈帧
--- No source file  ---------------------------------------------------------------------
...
--- C:\Program Files\Microsoft Visual Studio\MyProjects\1\1.cpp  ------------------------
10:
11:   int main()
12:   {
00401070 55                   push        ebp
00401071 8B EC                mov         ebp,esp
00401073 83 EC 4C             sub         esp,4Ch
00401076 53                   push        ebx
00401077 56                   push        esi
00401078 57                   push        edi
00401079 8D 7D B4             lea         edi,[ebp-4Ch]
0040107C B9 13 00 00 00       mov         ecx,13h
00401081 B8 CC CC CC CC       mov         eax,0CCCCCCCCh
00401086 F3 AB                rep stos    dword ptr [edi]
13:       int local1;
14:       int local2 = 0;
00401088 C7 45 F8 00 00 00 00 mov         dword ptr [ebp-8],0
15:       int sum = 0;
0040108F C7 45 F4 00 00 00 00 mov         dword ptr [ebp-0Ch],0
16:       sum = add(1,2,3,4);
00401096 6A 04                push        4
00401098 6A 03                push        3
0040109A 6A 02                push        2
0040109C 6A 01                push        1
0040109E E8 6C FF FF FF       call        @ILT+10(add) (0040100f)
004010A3 89 45 F4             mov         dword ptr [ebp-0Ch],eax ;调用完add函数,不需要恢复栈帧
17:       return 0;
004010A6 33 C0                xor         eax,eax
18:   }
004010A8 5F                   pop         edi
004010A9 5E                   pop         esi
004010AA 5B                   pop         ebx
004010AB 83 C4 4C             add         esp,4Ch
004010AE 3B EC                cmp         ebp,esp
004010B0 E8 1B 00 00 00       call        __chkesp (004010d0)
004010B5 8B E5                mov         esp,ebp
004010B7 5D                   pop         ebp
004010B8 C3                   ret
--- No source file  ---------------------------------------------------------------------

fastcall

fastcall将使用寄存器和栈结合的方式传递参数,ecx为第一个参数,edx为第二个参数,其余的参数从右向左入栈
将上面的代码改为


_fastcall int add(int a, int b, int c, int d)
{
	int local1;
	int local2 = 0;
	int sum = 0;
	sum = a + b + c + d;
	return sum;
}

int main()
{
	int local1;
	int local2 = 0;
	int sum = 0;
	sum = add(1,2,3,4);
	return 0;
}

汇编代码为

--- C:\Program Files\Microsoft Visual Studio\MyProjects\1\1.cpp  ------------------------
1:
2:    _fastcall int add(int a, int b, int c, int d)
3:    {
00401020 55                   push        ebp
00401021 8B EC                mov         ebp,esp
00401023 83 EC 54             sub         esp,54h
00401026 53                   push        ebx
00401027 56                   push        esi
00401028 57                   push        edi
00401029 51                   push        ecx
0040102A 8D 7D AC             lea         edi,[ebp-54h]
0040102D B9 15 00 00 00       mov         ecx,15h
00401032 B8 CC CC CC CC       mov         eax,0CCCCCCCCh
00401037 F3 AB                rep stos    dword ptr [edi]
00401039 59                   pop         ecx
0040103A 89 55 F8             mov         dword ptr [ebp-8],edx
0040103D 89 4D FC             mov         dword ptr [ebp-4],ecx
4:        int local1;
5:        int local2 = 0;
00401040 C7 45 F0 00 00 00 00 mov         dword ptr [ebp-10h],0
6:        int sum = 0;
00401047 C7 45 EC 00 00 00 00 mov         dword ptr [ebp-14h],0
7:        sum = a + b + c + d;
0040104E 8B 45 FC             mov         eax,dword ptr [ebp-4]
00401051 03 45 F8             add         eax,dword ptr [ebp-8]
00401054 03 45 08             add         eax,dword ptr [ebp+8]
00401057 03 45 0C             add         eax,dword ptr [ebp+0Ch]
0040105A 89 45 EC             mov         dword ptr [ebp-14h],eax
8:        return sum;
0040105D 8B 45 EC             mov         eax,dword ptr [ebp-14h]
9:    }
00401060 5F                   pop         edi
00401061 5E                   pop         esi
00401062 5B                   pop         ebx
00401063 8B E5                mov         esp,ebp
00401065 5D                   pop         ebp
00401066 C2 08 00             ret         8 ;从栈顶弹出返回地址(004010A9),将esp+4*4,跳转到返回地址
--- No source file  ---------------------------------------------------------------------
...
--- C:\Program Files\Microsoft Visual Studio\MyProjects\1\1.cpp  ------------------------
10:
11:   int main()
12:   {
00401070 55                   push        ebp
00401071 8B EC                mov         ebp,esp
00401073 83 EC 4C             sub         esp,4Ch
00401076 53                   push        ebx
00401077 56                   push        esi
00401078 57                   push        edi
00401079 8D 7D B4             lea         edi,[ebp-4Ch]
0040107C B9 13 00 00 00       mov         ecx,13h
00401081 B8 CC CC CC CC       mov         eax,0CCCCCCCCh
00401086 F3 AB                rep stos    dword ptr [edi]
13:       int local1;
14:       int local2 = 0;
00401088 C7 45 F8 00 00 00 00 mov         dword ptr [ebp-8],0
15:       int sum = 0;
0040108F C7 45 F4 00 00 00 00 mov         dword ptr [ebp-0Ch],0
16:       sum = add(1,2,3,4);
00401096 6A 04                push        4 ;第四个参数
00401098 6A 03                push        3 ;第三个参数
0040109A BA 02 00 00 00       mov         edx,2 ;第二个参数
0040109F B9 01 00 00 00       mov         ecx,1 ;第一个参数
004010A4 E8 6B FF FF FF       call        @ILT+15(add) (00401014) ;将地址004010A9压入栈,跳转到00401014处
004010A9 89 45 F4             mov         dword ptr [ebp-0Ch],eax
17:       return 0;
004010AC 33 C0                xor         eax,eax
18:   }
004010AE 5F                   pop         edi
004010AF 5E                   pop         esi
004010B0 5B                   pop         ebx
004010B1 83 C4 4C             add         esp,4Ch
004010B4 3B EC                cmp         ebp,esp ;比较ebp和esp的值
004010B6 E8 15 00 00 00       call        __chkesp (004010d0)
004010BB 8B E5                mov         esp,ebp
004010BD 5D                   pop         ebp
004010BE C3                   ret
--- No source file  ---------------------------------------------------------------------
          

__chkesp的作用

chkesp用来实现堆栈检查
将上面的程序修改为

_fastcall int add(int a, int b, int c, int d)
{
	int local1;
	int local2 = 0;
	int sum = 0;
	sum = a + b + c + d;
	return sum;
}

int main()
{
	int local1;
	int local2 = 0;
	int sum = 0;
	sum = add(1,2,3,4);
	_asm mov ebp,0 //修改ebp的值,产生错误
	return 0;
}

__chkesp函数 当ebp和esp的值不一致时,会调用_CrtDbgReport 函数,弹出报错的窗口

__chkesp:
004010D0 75 01                jne         __chkesp+3 (004010d3)
004010D2 C3                   ret
004010D3 55                   push        ebp
004010D4 8B EC                mov         ebp,esp
004010D6 83 EC 00             sub         esp,0
004010D9 50                   push        eax
004010DA 52                   push        edx
004010DB 53                   push        ebx
004010DC 56                   push        esi
004010DD 57                   push        edi
004010DE 68 30 20 42 00       push        offset string "The value of ESP was not properl"... (00422030)
004010E3 68 2C 20 42 00       push        offset string "" (0042202c)
004010E8 6A 2A                push        2Ah
004010EA 68 1C 20 42 00       push        offset string "i386\\chkesp.c" (0042201c)
004010EF 6A 01                push        1
004010F1 E8 BA 02 00 00       call        _CrtDbgReport (004013b0)
004010F6 83 C4 14             add         esp,14h
004010F9 83 F8 01             cmp         eax,1
004010FC 75 01                jne         __chkesp+2Fh (004010ff)
004010FE CC                   int         3
004010FF 5F                   pop         edi
00401100 5E                   pop         esi
00401101 5B                   pop         ebx
00401102 5A                   pop         edx
00401103 58                   pop         eax
00401104 8B E5                mov         esp,ebp
00401106 5D                   pop         ebp
00401107 C3                   ret

报错

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

_cdecl、_stdcall和_fastcall的区别 的相关文章

  • 启动httpd服务:SSLCertificateFile: file ‘/var/www/miq/vmdb/certs/server.cer‘ does not exist or is empty

    启动httpd服务 SSLCertificateFile file var www miq vmdb certs server cer does not exist or is empty 启动httpd服务 失败 复制代码 root te
  • UE5《Electric Dreams》项目PCG技术解析 之 理解Assembly(以SplineExample为例)

    文章目录 1 什么是Assembly 2 PCG部分 2 1 Assembly变换 2 2 Point变换 2 2 1 SG CopyPointsWithHierachy 2 2 2 过滤及点变换 2 2 3 ApplyHierachy 3
  • python 获取控制台输出内容 解决中文乱码

    Python获取控制台输出 1 使用subprocess库 非实时读取 import subprocess xe subprocess run iperf3 c 127 0 0 1 p 5668 J stdout subprocess PI
  • shell实现嵌入式软件看门狗

    shell实现嵌入式软件看门狗 长时间运行的嵌入式程序 有时会因为莫名其妙的原因挂掉 这时就需要有其他的程序来一直监控我们的程序 由于监控程序属于软件层面 因此这种程序被称为 软件看门狗 这里用一个shell脚本实现该功能 这个脚本会一直监
  • Nginx Lua 实战

    在 nginx conf 中配置 在 http 节点中配置 location staticitem get default type text html content by lua file lua staticitem lua 创建 s
  • vue中axios的参数位置整理

    每次在进行前后端联调的时候 总是因为参数放不对而影响进度 我人都麻了 真的记不住 还是整理一下以便后续开发 一 vue2和vue3的接口请求头 vue 2 const res await this axios get vue 3 const
  • 数据结构课程设计——客运订票系统

    目录 2需求分析 2 1系统功能 3总体设计 3 1功能模块图 4详细设计 4 1 详细的设计思路 车次设置 订票模块的功能 退票模块的功能 管理员模块的功能 4 2 算法流程图 5编码 5 1数据结构定义 1 乘客信息 2 候补队列乘客信
  • JAVA代码审计从入门到精通2-JAVA WEB动态调试

    动态调试 在代码开发和代码分析的过程中需要对代码进行动态调试 动态调试是指利用集成环境 IDE 自带的调试器跟踪软件运行 协助解决和分析软件的bug 动态调试需要对程序设置断点 通过对程序的某行代码设置断点 当程序运行到此代码处会自动停止
  • Qt:自定义信号变量类型

    1 定义变量类型 struct User STRUCT 预测结果 2 在定义后面添加声明 告知所有用到该信号变量的对象 建议1 2 3 放在一个头文件 供所有类包含 Q DECLARE METATYPE User STRUCT 3 incl
  • ajax实验,基于Ajax技术的实验管理系统

    摘要 本文的研究来源于常州纺织服装职业技术学院实验教学管理系统 是常州纺织服装职业技术学院教务管理系统的子系统 该系统主要完成制定实验教学计划 网上选课 三方互动 在深入研究Ajax技术原理和工作流程的基础上 提出一个基于Ajax技术的实验

随机推荐

  • 自定义类型-结构体

    注 本文为C语言初阶内容 目录 1 结构体 1 1结构体的基础知识 声明和自引用 1 2结构体变量的定义和初始化 1 3结构体内存对齐和修改默认对齐数 1 4结构体传参 1 结构体 1 1结构体的基础知识 声明 初始化和自引用 结构体是一些
  • js实现高德地图实现科技感3d建筑模型显示示例

  • java创建数组的方式_Java创建数组的几种方式总结

    1 一维数组的声明方式 type arrayName 或 type arrayName 附 推荐使用第一种格式 因为第一种格式具有更好的可读性 表示type 是一种引用类型 数组 而不是type类型 建议不要使用第二种方式 下面是典型的声明
  • 如何从Process维度评估芯片面积

    如何从Process维度评估芯片面积 文章右侧广告为官方硬广告 与吾爱IC社区无关 用户勿点 点击进去后出现任何损失与社区无关 最近在小编知识星球上有不少星友问到工艺 Metal Stack 的相关问题 今天小编将从最基础的 Metal S
  • R语言中的t分布函数:学生t分布实践

    R语言中的t分布函数 学生t分布实践 学生t分布是统计学中常用的概率分布之一 在数据分析和假设检验中具有重要的应用 本文将介绍如何在R语言中使用学生t分布函数进行实践 并提供相应的源代码 首先 我们需要了解学生t分布的基本特性和应用场景 学
  • 华为OD机试 - 五子棋迷(Java)

    题目描述 张兵和王武是五子棋迷 工作之余经常切磋棋艺 这不 这会儿又下起来了 走了一会儿 轮张兵了 对着一条线思考起来了 这条线上的棋子分布如下 用数组表示 1 0 1 1 1 0 1 0 1 1 棋了分布说明 1代表白子 0代表空位 1
  • 华为OD机试 - 比较两个版本号的大小(Java )

    题目描述 输入两个版本号 version1 和 version2 每个版本号由多个子版本号组成 子版本号之间由 隔开 由大小写字母 数字组成 并且至少有一个字符 按从左到右的顺序比较子版本号 比较规则如下 子版本号前面的0不参与比较 比如
  • 利用强化学习进行股票操作实战(四)

    本次实战代码仍是在之前基础上进行了一些修改 之前只在一支股票上进行训练 这次我将模型放在多支股票上训练 并在多支股票上进行了测试 对于多支股票的训练策略 没有参考过别人的训练方案 做这个的比较少 我按自己的理解去训练 每一轮训练 都将每支股
  • 芯片面积估计方法

    一 概念 芯片面积的主要涵盖部分分为三部分 IO 芯片的信号及电源pad等 Standard cell 实现芯片的功能逻辑 Macro block 第三方IP PLL DAC POR Memory etc 芯片面积估计就是通过目标工艺的库信
  • Python:使用 print 打印“Hello World!”以及其它字符内容

    哈喽 大家好 我是wangzirui32 这是我的第一篇博文 发现内容有误还请多多提出 谢谢 今天 我们将使用Python的print 来帮助我们让程序输出指定内容 如果你的Python版本是3 x print 将作为一个Python内置函
  • 第五周总结&实验报告三

    实验三 String类的应用 实验目的 掌握类String类的使用 学会使用JDK帮助文档 实验内容 1 已知字符串 this is a test of java 按要求执行以下操作 要求源代码 结果截图 1 统计该字符串中字母s出现的次数
  • 全国计算机等级考试题库二级C操作题100套(第79套)

    第79套 给定程序中 函数fun的功能是 求ss所指字符串数组中长度最短的字符串所在的行下标 作为函数值返回 并把其串长放在形参n所指变量中 ss所指字符串数组中共有M个字符串 且串长
  • js 查找字符串中指定字符 模糊查询 不区分大小写

    js 查找特定字符 模糊查询 不区分大小写 var str hello world hello coder 查找 HELLO 是否存在 找不到返回null var reg new RegExp HELLO i var isHas str m
  • Opencv-C++笔记 (12) : opencv-仿射变化

    文章目录 一 概述 二 GetRotationMatrix2D 三 warpAffine 一 概述 介绍完图像的缩放和翻转后 接下来将要介绍图像的旋转 但是在OpenCV 4中并没有专门用于图像旋转的函数 而是通过图像的仿射变换实现图像的旋
  • Python笔记:在Pandas中处理NaN值

    关于NaN值 在能够使用大型数据集训练学习算法之前 我们通常需要先清理数据 也就是说 我们需要通过某个方法检测并更正数据中的错误 任何给定数据集可能会出现各种糟糕的数据 例如离群值或不正确的值 但是我们几乎始终会遇到的糟糕数据类型是缺少值
  • vue element plus对话框第二次点击时 选择器不显示

    第一次点击时下拉框出现正常 关闭窗口后再次进入 选择器的下拉框不会出现 可给选择器设置属性 teleported false
  • AutoHotkey中的变量名 全局与局部冲突问题 - double-ref 双重引用

    文章目录 test 测试脚本 AutoHotkey中 全局变量与局部变量的作用域要缕清 已知一个 变量名foo 被一个全局变量 和 一个函数中的局部变量 使用 在该函数中 foo默认是局部变量 直接使用foo 其内容为空 双重解引用的变量
  • C++语言导学 第三章 模块化 - 3.4 名字空间

    C 语言导学 第三章 模块化 3 4 名字空间 3 4 名字空间 3 4 名字空间 除了函数 类和枚举之外 C 还提供了一种称为名字空间 namespace 的机制 用来表达某些声明属于一个整体以及它们的名字不会与其他名字冲突 例如 我希望
  • nodejs开启局域网广播获取ip通信

    bonjour 纯JavaScript中的Bonjour Zeroconf协议实现 使用多播DNS在本地网络上发布服务或发现现有服务 安装 npm install bonjour 使用方法 局域网A主机 import bonjour fro
  • _cdecl、_stdcall和_fastcall的区别

    概述 在windows开发环境中有三种觉的调用协议 分别为 cdecl C调用 stdcall 标准调用 fastcall 快速调用 三种调用方式有参数传递和栈帧恢复的方式有所不同 本文在结合汇编代码简要说明一下有三种调用方式的区别 环境