c 函数调用方式

一文搞明白的C函数调用方式与栈原理 当一个c函数被调用时,一个是如何被建立,又如何被消除的。这些细节跟操作系统平台及编译器的实现有关,下面的描述是针对运行在Intel奔腾芯片上Linux的gcc编译器而言。c语言的标准并没有描述实现的方式,所以,不同的编译器,处理器,操作系统都可能有自己的建立栈帧的方式。 阅读详情
通常在使用VC进行函数定义时会指定该函数调用方式,诸如:
  int __stdcall max(int a, int b)
  {
  return a>b?a:b;
  }
  int __cdecl min(int a, int b)
  {
  return a<b?a:b;
  }
  bool __fastcall equal(int a, int b)
  {
  return a=b?true:false;
  }
  首先,让我们来分个类,调用方法分为两大类另加一个较特殊的__thiscall.
  第一类:__stdcall类 别名:WINAPI,CALLBACK,PASCAL。该类特点是:主调函数负责参数入栈,由函数本身负责栈的恢复。
  第二类:__cdecl类 别名:C/C++中默认调用方式,若你定义函数未指定函数调用约定(Calling Conventions),例如在VC6中下面两个函数的调用约定是等价的:
  int max(int a, int b)
  {
  return a>b?a:b;
  }
  int __cdecl min(int a, int b)
  {
  return a<b?a:b;
  }
  该类调用约定的特点是:由主调函数负责参数入栈,并由主调函数负责线的恢复。
  第三类:__thiscall 该类比较特殊,只用于类成员函数调用,你甚至不能强制指定这个函数调用约定。它是由C/C++编译器自动添加的。在C/C++中类成员函数会默认传入一个this指针,对于此,在默入情况下,C/C++中类成员函数通过此类调用约定来指定this指针。
  接着介绍一下__thiscall,__thiscall是关于类的一种调用方式。
  它与其他调用方式的最大区别是:
  __thiscall对每个函数都增加了一个类指针参数
  class aa
  {
  void bb(int cc);
  };
  实际上bb的函数原形是void bb(aa &this, int cc);
  __cdecl的调用方式介绍: C和C++缺省调用方式
  例子:
  void Input( int &m,int &n);/*相当于void __cdecl Input(int &m,int &n);*/
  以下是相应的汇编代码:
  00401068 lea eax,[ebp-8] ;取[ebp-8]地址(ebp-8),存到eax
  0040106B push eax ;然后压栈
  0040106C lea ecx,[ebp-4] ;取[ebp-4]地址(ebp-4),存到ecx
  0040106F push ecx ;然后压栈
  00401070 call @ILT+5(Input) (0040100a);然后调用Input函数
  00401075 add esp,8 ;恢复栈
  从以上调用Input函数的过程可以看出:在调用此函数之前,首先压栈ebp-8,然后压栈ebp-4,然后调用函数Input,最后Input函数调用结束后,利用esp+8恢复栈。由此可见,在C语言调用中默认的函数修饰_cdecl,由主调用函数进行参数压栈并且恢复堆栈。
  下面看一下:地址ebp-8和ebp-4是什么? 在VC的VIEW->debug windows->Registers,显示寄存器变量值,然后在选debug windows->Memory,输入ebp-8的值和ebp-4的值(或直接输入ebp-8和-4),看一下这两个地址实际存储的是什么值,实际上是变量"n "的地址(ebp-8),m的地址(ebp-4)。
  由此可以看出:在主调用函数中进行实参的压栈并且顺序是从右到左。另外,由于实参是相应的变量的引用,也证明实际上引用传递的是变量的地址(类似指针)。
  总结:在C或C++语言调用中默认的函数修饰_cdecl,由主调用函数进行参数压栈并且恢复堆栈,实参的压栈顺序是从右到左,最后由主调函数进行堆栈恢复。由于主调用函数管理堆栈,所以可以实现变参函数。另外,命名修饰方法是在函数前加一个下划 线(_)。
  _stdcall调用约定介绍:实际上就是PASCAL,CALLBACK,WINAPI
  例子:
  void WINAPI Input( int &m,int &n);
  看一下相应调用的汇编代码:
  00401068 lea eax,[ebp-8]
  0040106B push eax
  0040106C lea ecx,[ebp-4]
  0040106F push ecx
  00401070 call @ILT+5(Input) (0040100a)
  从以上调用Input函数的过程可以看出:在调用此函数之前,首先压栈ebp-8,然后压栈ebp-4,然后调用函数Input,在调用函数Input之后,没有相应的堆栈恢复工作(为其它的函数调用,所以我没有列出)下面再列出Input函数本身的汇编代码:(实际此函数不大,但做汇编例子还是大了些,大家可以只看前和后,中间代码与此例子无关)
  39: void WINAPI Input( int &m,int &n)
  40: {
  00401110 push ebp
  00401111 mov ebp,esp
  00401113 sub esp,48h
  00401116 push ebx
  00401117 push esi
  00401118 push edi
  00401119 lea edi,[ebp-48h]
  0040111C mov ecx,12h
  00401121 mov eax,0CCCCCCCCh
  00401126 rep stos dword ptr [edi]
  41: int s,i;
  42:
  43: while(1)
  00401128 mov eax,1
  0040112D test eax,eax
  0040112F je Input+0C1h (004011d1)
  44: {
  45: printf(" Please input the first number m:");
  00401135 push offset string " Please input the first number m"… (004260b8)
  0040113A call printf (00401530)
  0040113F add esp,4
  46: scanf("%d",&m);
  00401142 mov ecx,dword ptr [ebp+8]
  00401145 push ecx
  00401146 push offset string "%d" (004260b4)
  0040114B call scanf (004015f0)
  00401150 add esp,8
  47:
  48: if ( m= s )
  004011B3 mov eax,dword ptr [ebp+8]
  004011B6 mov ecx,dword ptr [eax]
  004011B8 cmp ecx,dword ptr [ebp-4]
  004011BB jl Input+0AFh (004011bf)
  57: break;
  004011BD jmp Input+0C1h (004011d1)
  58: else
  59: printf(" m < n*(n+1)/2,Please input again! ");
  004011BF push offset string " m < n*(n+1)/2,Please input agai"… (00426060)
  004011C4 call printf (00401530)
  004011C9 add esp,4
  60: }
  004011CC jmp Input+18h (00401128)
  61:
  62: }
  004011D1 pop edi
  004011D2 pop esi
  004011D3 pop ebx
  004011D4 add esp,48h
  004011D7 cmp ebp,esp
  004011D9 call __chkesp (004015b0)
  004011DE mov esp,ebp
  004011E0 pop ebp
  004011E1 ret 8
  之后,我们看到在函数末尾部分,有ret 8,明显是恢复堆栈,由于在32位C++中,变量地址为4个字节(int也为4个字节),所以弹栈两个地址即8个字节。由此可以看出:在主调用函数中负责压栈,在被调用函数中负责恢复堆栈。因此不能实现变参函数,因为被调函数不能事先知道弹栈数量,但在主调函数中是可以做到的,因为参数数量由主调函数确定。
   下面再看一下,ebp-8和ebp-4这两个地址实际存储的是什么值,ebp-8地址存储的是n 的值,ebp -4存储的是m的值。说明也是从右到左压栈,进行参数传递。
  总结:_stdcall在主调用函数中负责压栈,在被调用函数中负责弹出堆栈中的参数,并且负责恢复堆栈。因此不能实现变参函数,参数传递是从右到左。另外,命名修饰方法是在函数前加一个下划线(_),在函数名后有符号(@),在@后面紧跟参数列表中的参数所占字节数(10进制),如:void Input(int &m,int &n),被修饰成: _Input@8  对于大多数api函数以及窗口消息处理函数皆用CALLBACK,所以调用前,主调函数会先压栈,然后api函数自己恢复堆栈。
  如:
  push edx
  push edi
  push eax
  push ebx
  call getdlgitemtexta
  最后,在SDK中输出API函数的时候,经常会利用WINAPI对函数进行约定,WINAPI在WIN32中,它被定义为__stdcall 函数调用约定有多种,这里简单说一下:
  1、__stdcall调用约定相当于16位动态库中经常使用的PASCAL调用约定。在32位的VC++5.0中PASCAL调用约定不再被支持(实际上它已被定义为__stdcall。除了__pascal 外,__fortran和__syscall也不被支持),取而代之的是__stdcall调用约定。两者实质上是一致的,即函数的参数自右向左通过栈传递,被调用的函数在返回前清理传送参数的内存栈,但不同的是函数名的修饰部分(关于函数名的修饰部分在后面将详细说明)。
  _stdcall是Pascal程序的缺省调用方式,通常用于Win32 Api中,函数采用从右到左的 压栈方式,自己在退出时清空堆栈。VC将函数编译后会在函数名前面加上下划线前缀,在函数名后加上"@"和参数的字节数。
  2、C调用约定(即用__cdecl关键字说明)按从右至左的顺序压参数入栈,由调用者把参数弹出栈。对于传送参数的内存栈是由调用者来维护的(正因为如此,实现可变参数的函数只能使用该调用约定)。另外,在函数名修饰约定方面也有所不同。
  _cdecl是C和C++程序的缺省调用方式。每一个调用它的函数都包含清空堆栈的代码,所以产生的可执行文件大小会比调用_stdcall函数的大。函数采用从右到左的压栈方式。VC将函数编译后会在函数名前面加上下划线前缀。是MFC缺省调用约定。
  3、__fastcall调用约定是“人”如其名,它的主要特点就是快,因为它是通过寄存器来传送参数的(实际上,它用ECX和EDX传送前两个双字(DWORD)或更小的参数,剩下的参数仍旧自右向左压栈传送,被调用的函数在返回前清理传送参数的内存栈),在函数名修饰约定方面,它和前两者均不同。
  _fastcall方式的函数采用寄存器传递参数,VC将函数编译后会在函数名前面加上"@"前缀,在函数名后加上"@"和参数的字节数。
  4、thiscall仅仅应用于“C++”成员函数。this指针存放于CX寄存器,参数从右到左压。thiscall不是关键词,因此不能被程序员指定。
  5、naked call采用1-4的调用约定时,如果必要的话,进入函数时编译器会产生代码来保存ESI,EDI,EBX,EBP寄存器,退出函数时则产生代码恢复这些寄存器的内容。naked call不产生这样的代码。naked call不是类型修饰符,故必须和_declspec共同使用。
字节对齐和C/C++函数调用方式学习总结 1)字节对齐和C/C++函数调用方式学习总结created: 04-06-17last saved: author: ayixidelu前言:《***软件编程规范》中提到:“在定义结构数据类型时,为了提高系统效率,要注意4字节对齐原则……”。本文解释x86上字节对齐的机制,其他架构读者可自行试验。同时,本文对C/C++的函数调用方式进行了讨论。1.先看下面的例子:struct A{  char 阅读详情

相关推荐

C/C++函数的调用约定详解

本文详细讲述C/C++函数调用约定相关的内容。

dvlinker的技术专栏 1万+

C语言函数调用方式的区别

通常在使用VC进行函数定义时会指定该函数调用方式,诸如:   int __stdcall max(int a, int b)   {   return a>b?a:b;   }   int __cdecl min(int a, int b)   {   return a   }   bool __fastcall equal(int a

程序员的自我修养_Will.zhang 975

C语言函数调用的几种方式

C语言中函数调用的方式包括普通函数调用、函数指针调用和函数回调。函数指针调用将函数视为指针,并通过指针间接调用函数。函数回调允许将一个函数作为参数传递给另一个函数,并在需要的时候进行回调。通过灵活运用这些函数调用方式,可以实现更加复杂和灵活的程序设计。的函数,该函数用于打印"Hello, World!函数接受一个函数指针作为参数,并在函数内部调用该函数。在上述代码中,我们首先声明了一个函数指针。的回调函数,该函数用于打印一条消息。在上述代码中,我们定义了一个名为。函数,从而实现了函数回调。

2301_79331328的博客 307

C/C++函数调用约定汇总

转: VC C/C++ 函数调用约定(最全) 函数调用约定 常见的函数调用约定[5]:cdecl , stdcall , fastcall , thiscall , naked call MFC调用约定(VS6:Project Settings-&gt;C/C++ Calling convention:) 1, __cdecl(C调用约定.The C default call...

乐行僧的博客 1430

c函数调用方式

cdecl 参数从右向左压栈 手动栈平衡 c/C++ MFC默认方式 _functionname stdcall 参数从右向左压栈 自动栈平衡 Win API _functionname@number //参数字节数 fastcall 左边开始的两个不大于4字节(DWORD)的参数分别放在ECX和EDX寄存器,其余的参数仍旧自右向左压栈传送 调用者清理栈 速度快 @functionname@number ////参数字节数 thiscall thiscall仅仅应用于"C++"成员函

daoer_sofu的专栏 346

微纳加工技术中的自对准硅化物(Silicide)工艺:关键步骤与应用场景解析

本文深入解析了微纳加工技术中的自对准硅化物(Silicide)工艺,详细介绍了其关键步骤与应用场景。从表面清洁、金属沉积到两步退火法,全面拆解工艺全流程,并探讨了不同技术节点下的工艺演进。文章还提供了实际应用中的问题排查方法和新兴技术对Silicide工艺的挑战,为芯片制造领域的工程师提供了实用参考。

weixin_30613727的博客 431

C/C++函数调用约定

函数调用约定就是函数调用者和被调用者之间的约定。函数调用约定决定了参数怎么传递以及由谁来平衡堆栈。 不同的编译器实现不一样。调用约定不显示指定的话默认是__cdecl。 这里主要讨论__cdecl和__stdcall 共同点:__cdecl和__stdcall参数入栈顺序都是从右到左 不同点: __cdecl由调用者清理堆栈,__stdcall由被调用者清理堆栈。 由于条件1的关系,约定...

回头太难 705

汽车底盘技术解析:从悬架调校到智能化,如何评价国产车底盘实力

汽车底盘作为决定车辆驾驶质感、安全性和耐久性的核心系统,其技术内涵远不止于悬架结构。从行驶系、转向系到制动系的协同工作,底盘调校是一门融合机械原理与工程实践的艺术。在电动化与智能化浪潮下,底盘技术正经历从被动适应到主动响应的变革,CDC可变阻尼减震器和空气悬架等技术的应用,让底盘具备了通过OTA升级实现性能优化的可能。国产汽车品牌如奇瑞、吉利等,通过平台化架构研发与调校经验积累,正推动底盘技术从“能用”向“好用”乃至“塑造独特驾驶风格”迈进。理解底盘技术,需超越简单的结构对比,关注其在实际路况中的滤震性、支

weixin_34413103的博客 387

C++语言(10)——C++标准库简介

文章来源:https://blog.51cto.com/9291927/2148678C++语言学习(十二)——C++语言常见函数调用约定 一、C++语言函数调用约定简介 C /C++开发中,程序编译没有问题,但链接的时候报告函数不存在,或程序编译和链接都没有错误,但只要调用库中的函数就会出现堆栈异常等现象。上述现象出现在C和C++的代码混合使用的情况下或在C++程序中使用第三方库(非C++语言开...

weixin_34194702的博客 223

DDS器件原理与应用(AD9833 AD9834)

是DDS的核心组成部分,用于实现相位的累加,并输出相应的幅值。相位累加器由M位宽加法器和M位宽寄存器组成,通过时钟控制,将上一次累加结果反馈到加法器输入端实现累加功能,从而使每个时钟周期内的相位递增数为,并取相位累加结果作为地址输出给ROM查找表部分。DDS的相位信息被存放在累加寄存器中,虽然幅值和相位不是线性关系,但寄存器累加值和相位可以是线性关系,很容易用寄存器的累加值表达相位信息。

m0_49968063的博客 6451

永磁同步电机解耦控制实战:从电流反馈到内模解耦的算法演进与选型指南

本文深入探讨了永磁同步电机高性能驱动中的核心挑战——交叉耦合问题,并对比分析了电流反馈解耦和内模解耦两大主流算法的原理、性能与适用场景。文章指出,电流反馈解耦动态响应快但对参数敏感,内模解耦鲁棒性更强但略有滞后,为工程师在不同应用需求下的算法选型提供了清晰的实战指南。

weixin_29039773的博客 265

图解 c语言 函数调用方式,C/C++函数调用的方式有哪些

C/C++函数调用的方式有哪些调用函数时,计算机常用栈来存储传递给函数的参数。你知道C/C++函数调用的方式有哪些吗?下面百分网小编带大家一起来看看详细内容,需要的朋友可以过来参考一下!想了解更多相关信息请持续关注我们应届毕业生考试网!栈是一种先进后出的数据结构,栈有一个存储区、一个栈顶指针。栈顶指针指向堆栈中第一个可用的数据项(被称为栈顶)。用户可以在栈顶上方向栈中加入数据,这个操作被称为压栈(...

weixin_39542043的博客 374

通过CN3口直接控制台达伺服电机A2-M(二)

既然可以通过RS485与伺服驱动器进行通讯,那么就肯定可以控制转速 首先,需要了解下 ‘控制模式及控制命令输入源设定’ 依据以上资料,速度控制模式有两种,S和SZ模式,分别对应模式选择中的02和04,对P1-01的地址0102进行写地址操作即可实现,一开始我使用了S模式,但是这个模式在寸动模式下会自动运转,不符合我控制的要求,后面改用SZ模式,就可以实现零速度。 使用串口工具发送命令:“01 06 01 02 00 04 28 35”即可以实现设置,设置完成后可以手动在伺服驱动器的按键面板上进行确

HKing_evil的博客 6826

c语言程序中函数调用本身叫什么,在C语言中函数调用方式有什么区别

在使用VC进行函数定义时,通常会指定该函数调用方式,那么在C语言中函数调用方式有什么区别呢?下面小编找到了一下教程,分享给大家,希望可以帮助到大家。通常在使用VC进行函数定义时会指定该函数调用方式,诸如:int __stdcall max(int a, int b){return a>b?a:b;}int __cdecl min(int a, int b){return a}bool __f...

weixin_32818917的博客 4918

ks-快手滑块验证码-Js逆向

本文分析了快手滑块验证码的破解过程。首先通过抓包找到验证码背景图接口,发现需要动态获取captchaSession参数。然后深入分析验证流程,发现verifyParam参数被加密处理,需要追踪其生成逻辑。文章详细解析了加密参数c的构成,包括captchaSn、滑动距离、轨迹信息等,并指出轨迹验证较为严格。最后通过对比浏览器和本地生成的加密值,确认加密逻辑正确,但指出轨迹生成仍需优化。作者建议参考相关文章深入分析轨迹逻辑,并提供了验证成功的截图作为参考。

2302_76420666的博客 1879

【AI生成】市面上主流自组网厂家的技术及市场研究

经过对全球自组网产业技术特征与市场格局的系统分析,本文得出以下核心结论:技术演进呈现智能化与融合化双轨路径 当前自组网技术创新已突破传统组网架构局限,形成"协议优化-架构创新-场景适配"的递进式发展路径。国际厂商聚焦智能算法应用,如Silvus采用深度学习实现动态拓扑优化,传输时延较传统方案降低37%;国内企业则侧重异构网络融合,中国移动设计院提出的5G LAN架构使工业场景通信可靠性提升至99.99%。

qq_31310977的博客 1698

C/C++函数调用的几种方式

我们知道,调用函数时,计算机常用栈来存放函数执行需要的参数,由于栈的空间大小是有限的,在windows下栈是向低地址扩展的数据结构,是一块连续的内存区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,windows下栈的大小是2M(也有的说是1M),如果申请的空间超过栈的剩余空间时,将提示overflow。 在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执

sunshinewave的专栏 7074

AE(自动曝光)调试策略:曝光曲线设计与过曝控制

自动曝光(AE, Auto Exposure)系统是图像质量控制链路中的核心模块之一,其性能直接决定了成像亮度是否稳定、细节是否完整、场景切换是否自然。在现代移动终端影像系统中,AE 不仅需要适应不同光照强度和复杂环境,还需兼顾人脸优先、HDR触发、视频帧率控制等多目标优化需求。本文基于高通 Snapdragon 和 MTK Dimensity 等主流平台的调试经验,系统梳理了 AE 模型设计原则、曝光曲线配置、测光策略选择与过曝抑制机制,并结合典型实战案例,提供可复制的工程落地路径。

努力分享一些人工智能、计算机视觉、影像等相关的知识干货! 3097

C语言中直接函数调用和间接函数调用的底层调用方式 X86 & AArch64

总结一下X86和AArch64架构下C语言中直接函数调用和间接函数调用的底层调用方式 1.直接函数调用 直接函数调用,话不多说,先上C代码 // test.c #include <stdio.h> void foo() { printf("function foo\n"); } int main(int argc, char **argv) { foo(); return 0; } 编译 gcc -O0 -o ex test.c 反汇编 objdump -d ex &&g

fightingxk的博客 2994

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

C语言 函数调用方式以及嵌套调用

C语言 函数调用方式以及嵌套调用

qq_48516121的博客 4320

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

c语言调用.h函数,C语言函数调用方式分享

C语言函数调用方式分享在C语言中函数的调用非常实用,如何调用函数成为常见的问题。大家知道C语言函数调用方式吗?通常在使用VC进行函数定义时会指定该函数调用方式,诸如:int __stdcall max(int a, int b){return a>b?a:b;}int __cdecl min(int a, int b){return a}bool __fastcall equal(int a...

weixin_33670352的博客 1577

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

C语言 | 函数调用的两种方式

C语言 | 函数调用的两种方式 #include <stdio.h> #include <stdlib.h> //方法1:声明->main函数(调用)->定义 void fun(int a, int b); /*1. 声明函数原型*/ int main() { int a, b; scanf("%d %d", &a, &b); fun(a, b); /*2. 函数调用*/ return 0; } void fun(in

weixin_44779122的博客 1132

C语言中函数参数有哪两种方式,c语言中函数调用的方式有哪些?

c语言中函数调用的方式有哪些?c语言中函数调用的方式:1.最常见的,直接调用void fun(void){......//你的代码.....}{.......fun();.....}2.用函数指针void fun(void){printf("OK!\n");}int main(void){void (*pfun)();pfun=fun;(*pfun)();return 0;}3.函数形参的方式vo...

weixin_42500156的博客 816

C/C++函数调用的几种方式总结

 本篇文章主要是对C/C++函数调用的几种方式进行了详细的总结介绍,需要的朋友可以过来参考下,希望对大家有所帮助 调用函数时,计算机常用栈来存储传递给函数的参数。 栈是一种先进后出的数据结构,栈有一个存储区、一个栈顶指针。栈顶指针指向堆栈中第一个可用的数据项(被称为栈顶)。用户可以在栈顶上方向栈中加入数据,这个操作被称为压栈(Push),压栈以后,栈顶自动变成新加

u011555996的博客 5096
上一篇: 标准C 类型转换
下一篇: c语言 函数 sprintf
zljjava
博客等级 码龄15年 155粉丝 15原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值