当前位置:网站首页>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]所创,转载请带上原文链接,感谢
边栏推荐
- The technology masters who ride the wind and waves gather again | Tencent cloud TVP continues to sail
- In depth analysis of the multi-user shopping mall system from search to create a profit point
- spark学习(三)--内存管理和性能调优
- OpenYurt 深度解读:如何构建 Kubernetes 原生云边高效协同网络?
- 史上最惨黑客:偷走10亿美元比特币7年未花,最终被司法部全数缴获
- Android字节跳动一面,被面试官吊打!幸得美团内推,三面拿到offer
- CCF BDCI热门赛题:非结构化商业文本信息中隐私信息识别
- Two ways for Tencent cloud server to build WordPress website
- 百万年薪架构师之路:谈应用系统架构设计
- [share] interface tests how to transfer files in post request
猜你喜欢

A letter to myself

要我说,多线程事务它必须就是个伪命题!

python中常见的一些错误异常类型

程序员买房前后对比,看完后已哭瞎...
![[operation and maintenance thinking] how to do a good job in cloud operation and maintenance services?](/img/3b/00bc81122d330c9d59909994e61027.jpg)
[operation and maintenance thinking] how to do a good job in cloud operation and maintenance services?

C language -- game of Sanzi

I do digital transformation in traditional industries (1)

EMQ X 在中国建设银行物联网平台中的应用EMQ X 在中国建设银行物联网平台中的应用

你这么不努力,怎么做年薪40W的大数据打工人?

5分钟GET我使用Github 5 年总结的这些骚操作!
随机推荐
深入探索 Android Gradle 插件的缓存配置
Infrastructure testing based on chef inspec
H5 official account listens to events in the closed browser (left fork).
Kubernetes v1.19.3 kubeadm deployment notes (2)
Using GaN based oversampling technique to improve the accuracy of model for mortality prediction of unbalanced covid-19
The technology masters who ride the wind and waves gather again | Tencent cloud TVP continues to sail
5分钟GET我使用Github 5 年总结的这些骚操作!
High quality defect analysis: let yourself write fewer bugs
Kubernetes V1.19.3 kubeadm 部署笔记(中)
Guest interview: Wang Jian
Booker · apachecn programming / back end / big data / AI learning resources 2020.11
Arthas install quick installation document
【分享】接口测试如何在post请求中传递文件
布客·ApacheCN 编程/后端/大数据/人工智能学习资源 2020.11
Hadoop learning (3) - Yarn
Explain three different authentication protocols in detail
设置背景图片的两种方式,并解决手机端背景图片高度自适应问题
Put method of immutablemap
岗位内推 | 微软亚洲研究院智能多媒体组招聘计算机视觉算法实习生
低功耗蓝牙单芯片为物联网助力