定义可变参数的函数
首先用#include "stdarg.h"
typedef char * va_list 这是va_list 在头文件 vadefs.h中的定义
先定义一个 va_list ap 用来保存参数的起始地址 这个是一个指针
第二步 利用va_start(ap,format) 来找到这个函数在栈中排列的
一堆参数的起始地址(函数的参数是倒序压入栈中的)
然后利用vsprintf 来读取字符串
最后用 va_end(ap)释放掉指针
下面就是模板
#include "stdarg.h"
void usart_printf(const char *format,...)
{
char string[200];
va_list ap;
va_start (ap,format);
vsprintf(string,format,ap);
va_end(ap);
usart_sendstring(string);
}
//下面是一些函数的函数原型
/*
函数原型:printf(const char *format,[argument]);
函数原型:sprintf(char *buffer, const char *format, [argument]);
函数原型: vsprintf(char *buffer, char *format, va_list param);
*/
//下面是一些资料
/*
先用
printf("a = %d, &a = %#x \n", a, (unsigned int)&a);
printf("b = %d, &b = %#x \n", b, (unsigned int)&b);
printf("c = %d, &c = %#x \n", c, (unsigned int)&c);
输出
a = 1, &a = 0x61fef0
b = 1, &b = 0x61fef4
c = 1, &c = 0x61fef8
由于 栈是向下生长的,即从高地址向低地址的方向分配内存。
可知 函数的参数压栈的顺序是从右到左。
printf是个变参函数 为了确定他的参数个数 我们需要通过某一个东西来
作为定标去判断参数有多少个个数 这也就是 为什么引入一个format,
我们可以根据format来判断出参数有多少个。
用户空间
栈空间:它用于维护函数调用的上下文,也就是我们本文的重点,
离开了栈,那么函数调用就无法实现了。它通常 在用户空间的的最高地址开始,
向下增长,也就是由高往低增长。
堆空间:堆空间是用来容纳应用程序动态分配内存的区域,
当我们用malloc函数时就是在这片区域分配内存,它是由低地址往高地址增长,
也就是向上增长。
可读可写区:
这里主要包含程序的data段,以及未初始化的变量段。
只读区:
这里包含了text段以及rodata段,好像在安卓系统上text段是可写的,
这里有待探究,有深入研究过的读者可以一起探讨。
预留空间:
也叫保留区,它不是一个单一的内存区域,而是对内存中受保护而禁止访问区域的总称,很小块
*/