鱼C论坛

 找回密码
 立即注册
查看: 2100|回复: 6

[已解决]请老师指点va_star()第二个参数是函数的最后一个参数名.而不是参数的数量哦

[复制链接]
发表于 2018-7-2 21:26:27 | 显示全部楼层 |阅读模式
10鱼币
本帖最后由 wow7jiao 于 2018-7-2 23:41 编辑

http://bbs.fishc.com/thread-77359-1-1.html


#include <stdio.h>
#include <stdarg.h>

int sum(int n, ...);

int sum(int n, ...) // 三个小点是占位符,表示参数个数不确定
{
        int i, sum = 0;
        va_list vap; // 定义参数列表

        va_start(vap, n); // 初始化参数列表,如果是 int sum(int gg, ...); 则这里应该是 va_start(vap, gg);<-------------我看来看去这里举例gg就是参数个数,没有明白那上面“函数的最后一个参数名”是什么意思?
        for (i = 0; i < n; i++)
        {
                sum += va_arg(vap, int); // 获取参数值
        }
        va_end(vap); // 首尾工作,关闭参数列表

        return sum;
}

int main()
{
        int result;

        result = sum(3, 1, 2, 3);

        printf("result = %d\n", result);

        return 0;
}
最佳答案
2018-7-2 21:26:28
请站在汇编语言的角度看问题
#include <stdio.h>
#include <stdarg.h>

int sum0(int n, ...)
{
        int sum = 0;
        void *p;

        p = &n;
        for(int i = 0; i < n; ++i)
        {
                ++(int *)p;
                sum += *(int *)p;
        }
        p = NULL;

        return sum;
}

int sum1(int n, ...)
{
        int sum = 0;
        va_list vap;

        va_start(vap, n);
        for(int i = 0; i < n; ++i)
        {
                sum += va_arg(vap, int);
        }
        va_end(vap);

        return sum;
}

int main(void)
{
        printf("%d\n", sum0(5, 100, 200, 300, 400, 500));
        printf("%d\n", sum1(5, 100, 200, 300, 400, 500));

        return 0;
}

来看看这两个函数有多相似
int sum0(int n, ...)
{
0137F290 55                   push        ebp  
0137F291 8B EC                mov         ebp,esp  
0137F293 81 EC E4 00 00 00    sub         esp,0E4h  
0137F299 53                   push        ebx  
0137F29A 56                   push        esi  
0137F29B 57                   push        edi  
0137F29C 8D BD 1C FF FF FF    lea         edi,[ebp-0E4h]  
0137F2A2 B9 39 00 00 00       mov         ecx,39h  
0137F2A7 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
0137F2AC F3 AB                rep stos    dword ptr es:[edi]  
        int sum = 0;
0137F2AE C7 45 F8 00 00 00 00 mov         dword ptr [sum],0  
        void *p;

        p = &n;
0137F2B5 8D 45 08             lea         eax,[n]  
0137F2B8 89 45 EC             mov         dword ptr [p],eax  

        for(int i = 0; i < n; ++i)
0137F2BB C7 45 E0 00 00 00 00 mov         dword ptr [ebp-20h],0  
0137F2C2 EB 09                jmp         sum0+3Dh (0137F2CDh)  
0137F2C4 8B 45 E0             mov         eax,dword ptr [ebp-20h]  
0137F2C7 83 C0 01             add         eax,1  
0137F2CA 89 45 E0             mov         dword ptr [ebp-20h],eax  
0137F2CD 8B 45 E0             mov         eax,dword ptr [ebp-20h]  
0137F2D0 3B 45 08             cmp         eax,dword ptr [n]  
0137F2D3 7D 16                jge         sum0+5Bh (0137F2EBh)  
        {
                ++(int *)p;
0137F2D5 8B 45 EC             mov         eax,dword ptr [p]  
0137F2D8 83 C0 04             add         eax,4  
0137F2DB 89 45 EC             mov         dword ptr [p],eax  

                sum += *(int *)p;
0137F2DE 8B 45 EC             mov         eax,dword ptr [p]  
0137F2E1 8B 4D F8             mov         ecx,dword ptr [sum]  
0137F2E4 03 08                add         ecx,dword ptr [eax]  
0137F2E6 89 4D F8             mov         dword ptr [sum],ecx  
        }
0137F2E9 EB D9                jmp         sum0+34h (0137F2C4h)  


        p = NULL;
0137F2EB C7 45 EC 00 00 00 00 mov         dword ptr [p],0  


        return sum;
0137F2F2 8B 45 F8             mov         eax,dword ptr [sum]  
}
0137F2F5 5F                   pop         edi  
0137F2F6 5E                   pop         esi  
0137F2F7 5B                   pop         ebx  
0137F2F8 8B E5                mov         esp,ebp  
0137F2FA 5D                   pop         ebp  
0137F2FB C3                   ret  
int sum1(int n, ...)
{
00FAF8F0 55                   push        ebp  
00FAF8F1 8B EC                mov         ebp,esp  
00FAF8F3 81 EC E4 00 00 00    sub         esp,0E4h  
00FAF8F9 53                   push        ebx  
00FAF8FA 56                   push        esi  
00FAF8FB 57                   push        edi  
00FAF8FC 8D BD 1C FF FF FF    lea         edi,[ebp-0E4h]  
00FAF902 B9 39 00 00 00       mov         ecx,39h  
00FAF907 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
00FAF90C F3 AB                rep stos    dword ptr es:[edi]  
        int sum = 0;
00FAF90E C7 45 F8 00 00 00 00 mov         dword ptr [sum],0  
        va_list vap;

        va_start(vap, n);
00FAF915 8D 45 0C             lea         eax,[ebp+0Ch]  
00FAF918 89 45 EC             mov         dword ptr [vap],eax  

        for(int i = 0; i < n; ++i)
00FAF91B C7 45 E0 00 00 00 00 mov         dword ptr [ebp-20h],0  
00FAF922 EB 09                jmp         sum1+3Dh (0FAF92Dh)  
00FAF924 8B 45 E0             mov         eax,dword ptr [ebp-20h]  
00FAF927 83 C0 01             add         eax,1  
00FAF92A 89 45 E0             mov         dword ptr [ebp-20h],eax  
00FAF92D 8B 45 E0             mov         eax,dword ptr [ebp-20h]  
00FAF930 3B 45 08             cmp         eax,dword ptr [n]  
00FAF933 7D 17                jge         sum1+5Ch (0FAF94Ch)  
        {
                sum += va_arg(vap, int);
00FAF935 8B 45 EC             mov         eax,dword ptr [vap]  
00FAF938 83 C0 04             add         eax,4  
00FAF93B 89 45 EC             mov         dword ptr [vap],eax  

00FAF93E 8B 4D EC             mov         ecx,dword ptr [vap]  
00FAF941 8B 55 F8             mov         edx,dword ptr [sum]  
00FAF944 03 51 FC             add         edx,dword ptr [ecx-4]  
00FAF947 89 55 F8             mov         dword ptr [sum],edx  
        }
00FAF94A EB D8                jmp         sum1+34h (0FAF924h)  


        va_end(vap);
00FAF94C C7 45 EC 00 00 00 00 mov         dword ptr [vap],0  


        return sum;
00FAF953 8B 45 F8             mov         eax,dword ptr [sum]  
}
00FAF956 5F                   pop         edi  
00FAF957 5E                   pop         esi  
00FAF958 5B                   pop         ebx  
00FAF959 8B E5                mov         esp,ebp  
00FAF95B 5D                   pop         ebp  
00FAF95C C3                   ret  

最佳答案

查看完整内容

请站在汇编语言的角度看问题 来看看这两个函数有多相似
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-7-2 21:26:28 | 显示全部楼层    本楼为最佳答案   
请站在汇编语言的角度看问题
#include <stdio.h>
#include <stdarg.h>

int sum0(int n, ...)
{
        int sum = 0;
        void *p;

        p = &n;
        for(int i = 0; i < n; ++i)
        {
                ++(int *)p;
                sum += *(int *)p;
        }
        p = NULL;

        return sum;
}

int sum1(int n, ...)
{
        int sum = 0;
        va_list vap;

        va_start(vap, n);
        for(int i = 0; i < n; ++i)
        {
                sum += va_arg(vap, int);
        }
        va_end(vap);

        return sum;
}

int main(void)
{
        printf("%d\n", sum0(5, 100, 200, 300, 400, 500));
        printf("%d\n", sum1(5, 100, 200, 300, 400, 500));

        return 0;
}

来看看这两个函数有多相似
int sum0(int n, ...)
{
0137F290 55                   push        ebp  
0137F291 8B EC                mov         ebp,esp  
0137F293 81 EC E4 00 00 00    sub         esp,0E4h  
0137F299 53                   push        ebx  
0137F29A 56                   push        esi  
0137F29B 57                   push        edi  
0137F29C 8D BD 1C FF FF FF    lea         edi,[ebp-0E4h]  
0137F2A2 B9 39 00 00 00       mov         ecx,39h  
0137F2A7 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
0137F2AC F3 AB                rep stos    dword ptr es:[edi]  
        int sum = 0;
0137F2AE C7 45 F8 00 00 00 00 mov         dword ptr [sum],0  
        void *p;

        p = &n;
0137F2B5 8D 45 08             lea         eax,[n]  
0137F2B8 89 45 EC             mov         dword ptr [p],eax  

        for(int i = 0; i < n; ++i)
0137F2BB C7 45 E0 00 00 00 00 mov         dword ptr [ebp-20h],0  
0137F2C2 EB 09                jmp         sum0+3Dh (0137F2CDh)  
0137F2C4 8B 45 E0             mov         eax,dword ptr [ebp-20h]  
0137F2C7 83 C0 01             add         eax,1  
0137F2CA 89 45 E0             mov         dword ptr [ebp-20h],eax  
0137F2CD 8B 45 E0             mov         eax,dword ptr [ebp-20h]  
0137F2D0 3B 45 08             cmp         eax,dword ptr [n]  
0137F2D3 7D 16                jge         sum0+5Bh (0137F2EBh)  
        {
                ++(int *)p;
0137F2D5 8B 45 EC             mov         eax,dword ptr [p]  
0137F2D8 83 C0 04             add         eax,4  
0137F2DB 89 45 EC             mov         dword ptr [p],eax  

                sum += *(int *)p;
0137F2DE 8B 45 EC             mov         eax,dword ptr [p]  
0137F2E1 8B 4D F8             mov         ecx,dword ptr [sum]  
0137F2E4 03 08                add         ecx,dword ptr [eax]  
0137F2E6 89 4D F8             mov         dword ptr [sum],ecx  
        }
0137F2E9 EB D9                jmp         sum0+34h (0137F2C4h)  


        p = NULL;
0137F2EB C7 45 EC 00 00 00 00 mov         dword ptr [p],0  


        return sum;
0137F2F2 8B 45 F8             mov         eax,dword ptr [sum]  
}
0137F2F5 5F                   pop         edi  
0137F2F6 5E                   pop         esi  
0137F2F7 5B                   pop         ebx  
0137F2F8 8B E5                mov         esp,ebp  
0137F2FA 5D                   pop         ebp  
0137F2FB C3                   ret  
int sum1(int n, ...)
{
00FAF8F0 55                   push        ebp  
00FAF8F1 8B EC                mov         ebp,esp  
00FAF8F3 81 EC E4 00 00 00    sub         esp,0E4h  
00FAF8F9 53                   push        ebx  
00FAF8FA 56                   push        esi  
00FAF8FB 57                   push        edi  
00FAF8FC 8D BD 1C FF FF FF    lea         edi,[ebp-0E4h]  
00FAF902 B9 39 00 00 00       mov         ecx,39h  
00FAF907 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
00FAF90C F3 AB                rep stos    dword ptr es:[edi]  
        int sum = 0;
00FAF90E C7 45 F8 00 00 00 00 mov         dword ptr [sum],0  
        va_list vap;

        va_start(vap, n);
00FAF915 8D 45 0C             lea         eax,[ebp+0Ch]  
00FAF918 89 45 EC             mov         dword ptr [vap],eax  

        for(int i = 0; i < n; ++i)
00FAF91B C7 45 E0 00 00 00 00 mov         dword ptr [ebp-20h],0  
00FAF922 EB 09                jmp         sum1+3Dh (0FAF92Dh)  
00FAF924 8B 45 E0             mov         eax,dword ptr [ebp-20h]  
00FAF927 83 C0 01             add         eax,1  
00FAF92A 89 45 E0             mov         dword ptr [ebp-20h],eax  
00FAF92D 8B 45 E0             mov         eax,dword ptr [ebp-20h]  
00FAF930 3B 45 08             cmp         eax,dword ptr [n]  
00FAF933 7D 17                jge         sum1+5Ch (0FAF94Ch)  
        {
                sum += va_arg(vap, int);
00FAF935 8B 45 EC             mov         eax,dword ptr [vap]  
00FAF938 83 C0 04             add         eax,4  
00FAF93B 89 45 EC             mov         dword ptr [vap],eax  

00FAF93E 8B 4D EC             mov         ecx,dword ptr [vap]  
00FAF941 8B 55 F8             mov         edx,dword ptr [sum]  
00FAF944 03 51 FC             add         edx,dword ptr [ecx-4]  
00FAF947 89 55 F8             mov         dword ptr [sum],edx  
        }
00FAF94A EB D8                jmp         sum1+34h (0FAF924h)  


        va_end(vap);
00FAF94C C7 45 EC 00 00 00 00 mov         dword ptr [vap],0  


        return sum;
00FAF953 8B 45 F8             mov         eax,dword ptr [sum]  
}
00FAF956 5F                   pop         edi  
00FAF957 5E                   pop         esi  
00FAF958 5B                   pop         ebx  
00FAF959 8B E5                mov         esp,ebp  
00FAF95B 5D                   pop         ebp  
00FAF95C C3                   ret  
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-7-3 08:43:40 | 显示全部楼层
应该是指的是一个变量,如果直接表示个数的话,常量就行了,或者该函数设计的时候就没必要加入该形参
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2018-7-3 10:54:38 | 显示全部楼层
https://blog.csdn.net/al86866365/article/details/56485178

好像意思 int n 是从栈里弹出的最后一个参数,作为结束地址
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2018-7-3 13:48:17 | 显示全部楼层
人造人 发表于 2018-7-3 11:14
请站在汇编语言的角度看问题

谢谢,人造人老师,我明白了,小甲鱼是说va_start()第二个参数要填变量n(上面写什么下面写什么),而不能填常量,例如5。&n是取一个标记地址。

PS:人造人老师,第12行代码 ++(int *)p,我用dev翻译显示错误不是左值,晚上我再回去vs试试。

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-7-3 18:01:34 | 显示全部楼层
wow7jiao 发表于 2018-7-3 13:48
谢谢,人造人老师,我明白了,小甲鱼是说va_start()第二个参数要填变量n(上面写什么下面写什么),而不 ...

现在呢
#include <stdio.h>
#include <stdarg.h>

int sum0(int n, ...)
{
        int sum = 0;
        void *p;

        p = &n;
        for(int i = 0; i < n; ++i)
        {
                //++(int *)p;
                p = (int *)p + 1;
                sum += *(int *)p;
        }
        p = NULL;

        return sum;
}

int sum1(int n, ...)
{
        int sum = 0;
        va_list vap;

        va_start(vap, n);
        for(int i = 0; i < n; ++i)
        {
                sum += va_arg(vap, int);
        }
        va_end(vap);

        return sum;
}

int main(void)
{
        printf("%d\n", sum0(5, 100, 200, 300, 400, 500));
        printf("%d\n", sum1(5, 100, 200, 300, 400, 500));

        return 0;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2018-7-3 21:46:07 | 显示全部楼层

++(int *)p这里p为什么是不是左值
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-30 00:37

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表