第2个回答 2020-01-03
首先先看到main函数中的不定参数:
1.引用:在Turbo
C2.0启动过程中,
传递main()函数三个参数:
argc,
argv和env。
*
argc:
整数,
鴐ain()的命令行参数个数。
*
argv:
字符串数组。
argv[0]
为程序运行的全路径名
argv[1]
为在DOS命令行中执行程序名后的第一个字符串;
argv[2]
为执行程序名后的第二个字符串;
...
argv[argc]为NULL。
*env:
字符串数组。env[]
的每一个元素都包含ENVVAR=value形式的字符
串。其中ENVVAR为环境变量。value
为ENVVAR的对应值
#include
#include
main(int
argc,
char
*argv[],
char
*env[])
{
int
i;
printf("%d\n",
argc);
/*
为什么它的输出是
1,
它到底是定义什么的,我看不明上面的解释*/
for(i=0;
i<=argc;
i++)
printf("argv[%d]:%s\n",
i,
argv[i]);
for(i=0;
env[i]!=NULL;
i++)
printf("
env[%d]:%s\n",
i,
env[i]);
}
argc,
argv,
env是在main()函数之前被赋值的,编译器生成的可执行文件,main()不是真正的入口点,而是一个标准的函数,这个函数名与具体的操作系统有关。
就想到其他函数是否能实现一样的功能,查询了相关资料,基本上都是利用STDARG.H中的
#define
va_start(ap,
parmN)
(ap
=
...)
#define
va_arg(ap,
type)
(*((type
*)(ap))++)
#define
va_end(ap)
定义如下:
typedef
char
*
va_list;
#define
va_start
_crt_va_start
#define
va_arg
_crt_va_arg
#define
va_end
_crt_va_end
#define
_crt_va_start(ap,v)
(
ap
=
(va_list)_ADDRESSOF(v)
+
_INTSIZEOF(v)
)
#define
_crt_va_arg(ap,t)
(
*(t
*)((ap
+=
_INTSIZEOF(t))
-
_INTSIZEOF(t))
)
#define
_crt_va_end(ap)
(
ap
=
(va_list)0
)
修改他人程序如下:
void
average(int
first,...)
{int
i=first;
va_list
maker;
va_start(maker,first);
while(i!=-1){
printf("%p:
%d\n",maker,i);
i=va_arg(maker,int);
}
}
void
main(void)
{
average(2,3,4,4,-1);
}
运行结果:
FFCE:
2
FFD0:
3
FFD2:
4
FFD4:
4
这个程序显示函数参数的地址相差2个字节
所以可以改写为:
void
x(char
*n,...)
{int
*p;
p=&n;
while(*p!=-1)
{printf("%p:%s\n",p,*p,*p);
p+=sizeof(char);}}
void
main()
{x("g","hfd","gfg","vsds",-1);}
运行结果:
FFD2:g
FFD4:hfd
FFD6:gfg
FFD8:vsds
不必通过宏va_start,va_arg,va_end实现
第3个回答 2008-04-03
int _Cdecl printf(const char *__format, ...);
Pointer to a list of arguments One of a series of arguments to which the functions apply a format specifier contained in *format Buffer where function writes the string Format string Stream where the functions output the formatted data
第4个回答 2020-05-18
//32
bit
汇编调用printf
//call
printf
(fmt,a1,a1,a3,a4.....an)
;调用的数据压入栈,由于宽度不知道,所以用伪代码表示.
push
a5
push
a4
push
a3
push
a2
push
a1
push
offset
fmt
call
printf
sub
esp,sizeof(an)+..........+sizeof(a4)+sizeof(a3)+sizeof(a2)+sizeof(a1)
printf
的c实现
//实际上
用汇编的时候,跳过返回地址就是所有参数的首地址
//mov
ebx
,dword
ptr
esp[8]
;
//fmt
的地址
//mov
esi,
dowrd
ptr
esp[12]
//a1的地址
char**pvarlist=
&fmt;//fmt
在堆栈最低端。是个地址,所以他的地址就是所有参数的首地址
pvarlist++;
for(
i=0;i
评论
0
0
加载更多