小知识点总结:(知识点2、3是为了更好理解知识点1)
知识点1:va_list、 va_start、 vsprintf、va_end 用法:
看同事LCD工程里面有这样的应用--
va_list arg_ptr;
va_start(arg_ptr, format);
slen = vsprintf(buf, format, arg_ptr);
va_end(arg_ptr);
百度后的最容易理解的解析:--用法
(1)首先在函数里定义一具VA_LIST型的变量,这个变量是指向参数的指针
(2)然后用VA_START宏初始化变量刚定义的VA_LIS T变量,这个宏的第二个参数是第一个可变参数的前一个参数,是一个固定的参数。
(3)然后用VA_ARG返回可变的参数,VA_ARG的第二个参数是你要返回的参数的类型。
(4)最后用VA_END宏结束可变参数的获取。然后你就可以在函数里使用第二个参数了。如果函数有多个可变参数的,依次调用VA_ARG获取各个参数。
实例:
- /* 函数名: vsprintf
- 功 能: 送格式化输出到串中
- 返回值: 正常情况下返回生成字串的长度(除去\0),错误情况返回负值
- 用 法: int vsprintf(char *string, char *format, va_list param);
- // 将param 按格式format写入字符串string中
- 注: 该函数会出现内存溢出情况,建议使用vsnprintf
- 程序例:
- */
- #include <stdarg.h>
- char buffer[80];
- int vspf(char *fmt, ...)
- {
- va_list argptr;
- int cnt;
- va_start(argptr, fmt);
- cnt = vsprintf(buffer, fmt, argptr);
- va_end(argptr);
- return(cnt);
- }
- int main(void)
- {
- int inumber = 30;
- float fnumber = 90.0;
- char string[4] = "abc";
- vspf("%d %f %s", inumber, fnumber, string);
- printf("%s\n", buffer);
- return 0;
- }
- 该程序结果为
- 30 90.000000 abc
在进程中,堆栈地址是从高到低分配的.当执行一个函数的时候,将参数列表入栈,压入堆栈的高地址部分,然后入栈函数的返回地址,接着入栈函数的执行代码,这个入栈过程,堆栈地址不断递减,一些黑客就是在堆栈中修改函数返回地址,执行自己的代码来达到执行自己插入的代码段的目的.
总之,函数在堆栈中的分布情况是:地址从高到低,依次是:函数参数列表,函数返回地址,函数执行代码段.
堆栈中,各个函数的分布情况是倒序的.即最后一个参数在列表中地址最高部分,第一个参数在列表地址的最低部分.参数在堆栈中的分布情况如下:
最后一个参数
倒数第二个参数
...
第一个参数
函数返回地址
知识点3:堆栈分布及其设置
C/C++
例子程序
1
2
3
4
5
6
7
8
9
10
11
12
13
|
//main.cpp
int
a = 0;
//全局初始化区
char
*p1;
//全局未初始化区
main()
{
int
b;
//栈
char
s[] =
"abc"
;
//栈
char
*p2;
//栈
char
*p3 =
"123456"
;
//123456\0在常量区,p3在栈上。
static
int
c =0;
//全局(静态)初始化区
p1 = (
char
*)
malloc
(10);
p2 = (
char
*)
malloc
(20);
//分配得来的10和20字节的区域就在堆区。
}
|