当前位置:网站首页>Implement printf function by yourself
Implement printf function by yourself
2020-11-09 15:25:00 【shzwork】
origin:https://www.e-learn.cn/content/qita/716071
First of all, let's take a look at the basics .
printf The format characters are as follows ,
Format characters |
explain |
d |
Output integers in signed decimal form ( Integers do not output symbols ) |
u |
Output integers in unsigned decimal form |
x |
Output an integer in hexadecimal unsigned form ( Don't output preamble 0x), use x Then output hexadecimal number of a~f In lower case |
c |
Output in character form , Only one character is output |
s |
Output string |
stay C In language , Not only is the type of the parameter variable , And the number of parameters is also variable . in other words , In the formal parameter list, you can not explicitly specify the number and type of parameters to be passed , As mentioned above printf That's what functions do . This function is called a variable parameter function . The number and type of parameters of variable length parameter function are variable , But its design principle is consistent with that of fixed parameter function , We have a way to tell the variable parameter function the number and type of parameters that are not specified .
printf The statement of :
int printf(const char *format, ...);
format: Fixed parameter
... : Variable parameters ( Variable parameter )
stay C In language , The declaration of the variable parameter function is placed in atdarg.h In the standard library , Of course, you can include it directly and use it , But we define it here ( Refer to the macro definition of the header file ).
typedef char * va_list;
/* When sizeof(n)=1/2/4 when ,_INTSIZEOF(n)=4 */
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
//#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
//#define va_arg(ap,t) (ap = ap + _INTSIZEOF(t), *(t *)(ap - _INTSIZEOF(t)))
/* The meaning of the following words is , First point to the address of the next variable , And then again ( reduce ) Come back , Finally, take the value in its original address */
#define va_arg(ap,t) (*(t *)(ap = ap + _INTSIZEOF(t), ap - _INTSIZEOF(t)))
/* When the pointer runs out, it points to 0 Address , Prevent the appearance of wild pointer */
#define va_end(ap) ( ap = (va_list)0 )
There's a little bit of caution here #define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) -1) & ~(sizeof(int) - 1) ), It may not be easy to understand , Here is a knowledge point : Because in x86(32 Bit machine ) Under the platform ,GCC By default, the compiler presses 4 Byte alignment , So when sizeof(n)=1/2/4 when ,_INTSIZEOF(n)=4 When the variable type is char,unsigned int,int, That's not enough 4 All bytes are in accordance with 4 Byte completion .
Here's how My_printf.c
#include "my_printf.h"
//==================================================================================================
typedef char * va_list;
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
//#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define va_arg(ap,t) ( *(t *)( ap=ap + _INTSIZEOF(t), ap- _INTSIZEOF(t)) )
#define va_end(ap) ( ap = (va_list)0 ) // There is no explanation here , It's not difficult to understand.
//==================================================================================================
unsigned char hex_tab[]={'0','1','2','3','4','5','6','7',\
'8','9','a','b','c','d','e','f'}; // Output characters in various bases
static int outc(int c)
{
__out_putchar(c); // there _out_putchar In fact, that is putchar, stay .h In the definition of
return 0;
}
static int outs (const char *s) // Output string
{
while (*s != '\0')
__out_putchar(*s++);
return 0;
}
static int out_num(long n, int base,char lead,int maxwidth)
{
unsigned long m=0;
char buf[MAX_NUMBER_BYTES], *s = buf + sizeof(buf); // sizeof It's the ending '\0' ,strlen not
int count=0,i=0; // Note that there s Point to buf The end of , As for why to keep looking down
*--s = '\0'; // First --, At the end of assignment , because sizeof Count the length inside the terminator
if (n < 0){
m = -n; // If the output is a negative number, it is negated
}
else{
m = n;
}
do{
*--s = hex_tab[m%base];
count++;
}while ((m /= base) != 0); // The number to be printed is stored in the array from bits to bits buf in , If it doesn't point to buf end ,
if (n < 0)
*--s = '-'; // If it's negative, add a minus sign
return outs(s);
}
/*reference : int vprintf(const char *format, va_list ap); */
static int my_vprintf(const char *fmt, va_list ap)
{
char lead=' ';
int maxwidth=0;
for(; *fmt != '\0'; fmt++)
{
if (*fmt != '%') { // Order search judgment , encounter % On the launch , Otherwise, continue to loop out the output
outc(*fmt);
continue;
}
fmt++;
if(*fmt == '0'){ // encounter ‘0’ Explain that the preamble is 0
lead = '0';
fmt++;
}
while(*fmt >= '0' && *fmt <= '9'){ // The next number is the length , Calculate the specified length
maxwidth *=10;
maxwidth += (*fmt - '0');
fmt++;
}
switch (*fmt) { // Determine the format output
case 'd': out_num(va_arg(ap, int), 10,lead,maxwidth); break;
case 'o': out_num(va_arg(ap, unsigned int), 8,lead,maxwidth); break;
case 'u': out_num(va_arg(ap, unsigned int), 10,lead,maxwidth); break;
case 'x': out_num(va_arg(ap, unsigned int), 16,lead,maxwidth); break;
case 'c': outc(va_arg(ap, int )); break;
case 's': outs(va_arg(ap, char *)); break;
default:
outc(*fmt);
break;
}
}
return 0;
}
//reference : int printf(const char *format, ...);
int printf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
my_vprintf(fmt, ap);
va_end(ap);
return 0;
}
int my_printf_test(void)
{
printf("My_printf test\n\r") ;
printf("test char =%c,%c\n\r", 'A','a') ;
printf("test decimal number =%d\n\r", 123456) ;
printf("test decimal number =%d\n\r", -123456) ;
printf("test hex number =0x%x\n\r", 0x55aa55aa) ;
printf("test string =%s\n\r", "yoyoyo") ;
printf("num=%08d\n\r", 12345);
printf("num=%8d\n\r", 12345);
printf("num=0x%08x\n\r", 0x12345);
printf("num=0x%8x\n\r", 0x12345);
printf("num=0x%02x\n\r", 0x1);
printf("num=0x%2x\n\r", 0x1);
printf("num=%05d\n\r", 0x1);
printf("num=%5d\n\r", 0x1);
return 0;
}
The experimental results are as follows :
版权声明
本文为[shzwork]所创,转载请带上原文链接,感谢
边栏推荐
- 布客·ApacheCN 编程/后端/大数据/人工智能学习资源 2020.11
- 瞧瞧,这样的『函数』才叫 Pythonic
- Rongyun has completed several hundred million RMB round D financing, and will continue to build global cloud communication capability
- 堆重启_uaf_hacknote
- iOS中的内嵌汇编
- 5分钟GET我使用Github 5 年总结的这些骚操作!
- Kubernetes v1.19.3 kubeadm deployment notes (2)
- Using fastai to develop and deploy image classifier application
- Data consistency of cache
- EMQ X 在中国建设银行物联网平台中的应用EMQ X 在中国建设银行物联网平台中的应用
猜你喜欢
Embedded assembly in IOS
I heard that you changed your registered residence overnight. How can you help yourself if you work like ping?
Learning history of C language
AUTOCAD2020安装包&安装教程
岗位内推 | 微软亚洲研究院智能多媒体组招聘计算机视觉算法实习生
C language -- game of Sanzi
Super discount, cloud server 88 yuan seconds
懒得写文档,swagger文档导出来不香吗
Cad2016 software installation tutorial
Put method of immutablemap
随机推荐
Flink的安装和测试
高德全链路压测——语料智能化演进之路
H5 official account listens to events in the closed browser (left fork).
5 minutes get I use GitHub's 5-year summary of these operations!
百万年薪架构师之路:谈应用系统架构设计
Native地图与Web融合技术的应用与实践
Object oriented magic method collection
MES系统在行业应用里区别于传统式管理
听说你一夜之间变了户籍,依萍如洗的打工人该如何自救?
A letter to myself
spark学习(二)--作业调度和shuffle解析
低功耗蓝牙单芯片为物联网助力
使用art-Template模板获取天气预报信息
High quality defect analysis: let yourself write fewer bugs
CCF BDCI hot topic: privacy information recognition in unstructured business text information
瞧瞧,这样的『函数』才叫 Pythonic
To me, multithreading transaction must be a pseudo proposition!
MES system plays an important role in the factory production management
C language -- game of Sanzi
shell脚本快速入门----shell基本语法总结