printf函数原理和格式化字符串

【纯干货】深度底层剖析,你所不知道的printf 文章目录注意视频再观printf函数print为什么要加个f格式符是什么时候被解析的?如何实现变参函数来实现一个printf吧printf是否有检测功能printf只能输出在命令行吗结语 注意 本文为针对C语言的基础技术向,更适合刚入门需要进阶的同学技术进阶使用,当然我会尽量用简单的语言让哪怕是初学者也可以看得懂,核心知识有如下部分: 变参函数的概念和使用 __attribute__(())的概念和使用 printf函数的实现 视频 本文可以结合视频一起食用,效果更佳:视频链接 再观printf函数 相 阅读详情

1、printf函数原理

如果遇到普通字符,直接输出。
如果遇到格式说明符(如 %d、%f 等),则根据说明符的类型从参数列表(va_list)中取出对应的值,并按照指定的格式进行转换,这一句话其实描述的是va_arg(ap, t)这个函数的功能。 然后再输出转换后的字符串。
而ap就是参数列表,它的结构体在arch64架构是这样定义的

    typedef struct __va_list {
      void *__stack; // 指向堆栈上的参数区域
      void *__gr_top;  // 通用寄存器区域的顶部指针
      void *__vr_top;  // 浮点寄存器区域的顶部指针
      int __gr_offs;  // 通用寄存器的偏移量
      int __vr_offs;  // 浮点寄存器的偏移量
    } va_list;

整数参数可能存储在通用寄存器中,浮点参数存储在浮点数寄存器中,多余的参数存储在堆栈上。

2、格式字符串

格式字符串可以包含普通字符和格式说明符(以 % 开头)。
常见格式说明符

  • %d 或 %i:十进制整数。
  • %u:无符号十进制整数。
  • %f:浮点数(默认显示 6 位小数)。
  • %lf:双精度浮点数(与 %f 等效)。
  • %c:单个字符。
  • %s:字符串。
  • %x 或 %X:十六进制整数(小写或大写)。
  • %o:八进制整数。
  • %%:输出一个 % 符号。

格式修饰符
格式说明符还可以带有修饰符,用于控制输出的宽度、精度等:

  • 宽度修饰符:%5d(表示输出宽度为 5 个字符,不足部分用空格填充)。
  • 精度修饰符:%.2f(表示浮点数保留 2 位小数)。
  • 对齐方式:%-5d(左对齐)。
  • 填充字符:%05d(用 0 填充)。

3、参考

https://mp.weixin.qq.com/s/LRK9Byd7UqVqctB9rY1rjw
https://mp.weixin.qq.com/s/_4MvlMQOcSEBzI-5SN-CTg

自己动手用C语言实现迷你printf函数 可变参数函数简单解读(variadic function) 平时写代码接触最多函数大概就是 printf 函数了,printf 函数就是一个可变参数函数,第2个参数就是可变参数,第一个参数是格式化字符串。格式化字符串中的转换修饰符决定了可变参数的数量和类型。 int printf (const char *format, ...) 可变参数函数(variadic function):函数参数变量... 阅读详情

相关推荐

C语言 printf函数实现

printf()是控制台程序中最常用的函数,作用是输入的字符、数字等信息拼成完整的句子并且输出到标准输出设备(显示器、控制台等)。 下面是printf()定义:int printf(const char *fmt, ...)printf()实现部分:int Test_printf(const char *fmt, ...) { //定义接收输出信息最大长度1024字节 char

大昱的博客 6019

printf打印函数的原理浅析

printf的底层原理浅析 前言   最近在学习linux内核的时候用到了自定义实现的printf,学习了一下,在此记录,希望有助于大家。   在C语言中,我们用到的最多的输出功能函数大概就是printf了。但以前只是调用C语言的库函数,具体printf是如何实现的呢? 说到底两件事: (1)、函数变参 (2)、格式解析   下面将简要介绍以上两点内容,最后附一个简单的printf例子。 函数变参...

xiaopan的博客 7336

自定义简易的printf函数实现

本文中,我们通过使用C语言的可变参数功能,创建了一个简单的printf函数的实现。尽管这个函数的实现比较简单,但它能够处理常见的格式化字符,并将格式化后的结果输出到标准输出设备。实际上,标准库中的printf函数比我们的实现要复杂得多,它支持更多的格式化选项和功能。然而,通过这个简单的实现,我们可以更好地理解printf函数的工作原理和可变参数的使用方法。首先,让我们定义一个名为my_printf的函数,它将接收一个格式化字符串和一系列参数,并将其格式化后的结果输出到标准输出设备。对于字符串,我们使用。

Byte_O_O的博客 715

C 语言的可变参数表函数的设计

首先在介绍可变参数表函数的设计之前,我们先来介绍一下最经典的可变参数表printf函数的实现原理。一、printf函数的实现原理 在C/C++中,对函数参数的扫描是从后向前的。C/C++的函数参数是通过压入堆栈的方式来给函数传参数的(堆栈是一种先进后出的数据结构),最先压入的参数最后出来,在计算机的内存中,数据有2块,一块是堆,一块是栈(函数参数及局部变量在这里),而栈是从内存的高地址向低地址生...

java开发指南博客 【转载】 550

GD32F307 USB主机模式 外接U盘升级 调试问题记录

在移植USB驱动做主机读U盘时遇到的问题。 问题1、移植USB驱动完成后,插入U盘,一直在 usbh_core_task 的默认case 和测试case中反复执行无法执行到后面的连接及以后得步骤。 问题2、在 usbh_core_task 函数中,一直卡在枚举的case,无法执行下面操作。具体卡在urb_wait的while循环无法跳出。

LGC_764385701的博客 1949

深入解析磁盘性能测试:vdbench与fio的实战对比

本文深入对比了磁盘性能测试两大工具vdbench与fio的核心定位与实战应用。vdbench擅长多客户端、可编排的存储系统集成测试,而fio则以灵活的单机深度定制见长,是测试硬件极限和模拟特定应用IO模型的利器。文章通过安装指南、参数解析和典型场景对比,帮助读者根据需求选择合适工具,精准评估磁盘性能。

weixin_29300931的博客 331

printf的实现原理

要了解变参函数的实现,首先我们的弄清楚几个问题: 1: 该函数有几个参数。 2: 该函数怎样去访问这些参数。 3: 在访问完成后,如何从堆栈中释放这些参数。 函数变参 对于c语言,它的调用规则遵循_cdedl调用规则。 在_cdedl规则中: 1. 参数从右到左依次入栈 2. 调用者负责清理堆栈 3. 参数的数量类型不会导致编译阶段的错误 printf的声明: int _cdecl printf(const char* for...

sy_123a的专栏 3116

Labview及NI-USRP驱动安装教程

软件下载 安装使用的LabVIEW2018及NI-USRP驱动程序已上传,下载地址: 天翼云盘链接 (访问码:oc33) 百度网盘链接 (提取码:88mi) (注:天翼云盘下载不限速) LabVIEW2018安装步骤 右键软件压缩包选择解压至LabVIEW2018 选中文件,鼠标右击选择以管理员身份打开2018LV-WinChn.exe文件。 点击确定。 点击Unzip解压。 点击确定。 点击下一步。 填写任意信息后,点击下一步。 点击下一步。 点击浏览更改安装路径建议安装到除C盘以

dadapongi6的博客 2万+

格式化字符串攻击原理及示例

类printf函数实现原理;格式化字符串攻击原理及示例

么刚的专栏 1万+

Unreal 5 MetaHuman插件全流程:从安装到角色动画生成

本文详细介绍了Unreal 5中MetaHuman插件的全流程使用指南,从安装配置到角色动画生成。通过Quixel Bridge下载预设角色,利用面部捕捉技术赋予数字人模型生命力,并提供材质编辑、性能优化等进阶技巧,帮助用户快速创建照片级真实的虚拟角色。

weixin_29009081的博客 831

海康DS-7604N-K1/RTB固件包

【摘要】海康DS-7604N-K1/RTB萤石云设备发布V4.30.091版本升级程序(2022.09.19),仅适用于指定型号。升级前需先升级至V3.4.106基础版本,刷机会重置设备为未激活状态,需重新设置admin密码。该机型支持密码/手势登录,无密码时可通过U盘升级。注意事项:升级存在风险,需确认程序适用性;升级过程严禁断电;必须阅读压缩包内的刷机说明。此为定制机型,非必要不建议升级。(150字)

海康威视技术支持 1578

pwn学习(格式化字符串漏洞)

格式化字符串函数介绍 格式化字符串函数可以接受可变数量的参数,并将第一个参数作为格式化字符串,根据其来解析之后的参数,通俗来说。格式化字符串函数就是将计算机内存中表示的数据转化为我们人类可读的字符串格式。一般来说,格式化字符串在利用时分为三个部分。 格式化字符串函数 格式化字符串 后续参数(可选) Example printf("my name is %s, age is %d.", "das...

至臻求学,胸怀云月 2348

VxWorks系列 快速导航

Vxworks系列快速阅览导航

Mr.Sugarcane 1309

四、E906移植----printf函数重映射至uart

玄铁riscv核E906的fpga移植04篇,printf函数重映射至串口

qq_40011737的博客 2570

手把手教你学Simulink--FIR滤波器的设计与优化仿真

FIR滤波器的设计目标通常包括指定的频率响应特性(如低通、高通、带通或带阻),以及特定的应用需求(如线性相位、最小化误差等)。Simulink提供了一个直观且强大的平台来模拟这些设计,并允许用户通过调整参数实时观察其对系统性能的影响。明确你的系统需求,比如输入信号类型(如正弦波组合)、采样率、FIR滤波器的设计参数(如滤波器类型、阶数、截止频率等)。假设我们需要设计一个低通FIR滤波器,用来去除高于1kHz的所有频率成分,保留低于1kHz的信号成分。采样率为8kHz。

MHD0815的博客 348

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

漏洞分析实践_格式化字符串漏洞

格式化字符串是由普通字符串和格式化规定字符构成的字符序列。普通字符会原封不动地复制到输出流中,而格式化规定字符以。

kitsch0x97的博客 1280

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

PWN--格式化字符串

‌格式化字符串‌是指在编程过程中,通过特殊的占位符将相关对应的信息整合或提取的规则字符串。格式化字符串包括格式化输入和格式化输出,其本质是程序员调用相关格式化字符串的操作协议规定。错误的或不当的信息配置可能导致程序运行失效或产生未定义行为在PWN中,格式化字符串漏洞是常见的考察点,仅次于栈溢出漏洞。格式化字符串漏洞成因:程序使用了格式化字符串作为参数,并且格式化字符串为用户可控。其中触发格式化字符串漏洞函数主要是、、、等C库中家族函数格式化说明符 CPU利用ebp访问栈内东西 printf函数参数从右边

cyy001128的博客 698

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

printf 函数的原理以及在单片机上重定向至LCD12832的实现

首先,printf 函数的的原型是这样的: int printf(char const * format, ...); *format 就是要格式化的字符串的起始地址。注意这个必须是字符串以'\0' 为结尾,否则格式化的的时候会以指针为起点一直向后格式化,直到在后面连续的内存中遇到一个'\0' 后面的 ”...“ 是变参列表。可变参数列表是通过宏来实现的,这些宏定义在 stdarg.h里。这

mazhao141的博客 3242

模拟实现printf函数,完成函数调用

通过函数原型可以看出printf函数其实是一个可变参数函数,在printf函数中只需要知道传入函数的第一个参数,就可以根据该参数在栈中的存储位置获取后面参数的位置及信息了。 printf函数第一个参数const cahr *format,该字符串内包含并确定了后面参数的输出格式,比如"%c","%d","%d","%x"等等。 printf函数返回值,就是通过该函数打印到标准输出流(屏

sherry_zhe的博客 835

浅谈C的printf

printf()函数是格式化输出函数, 一般用于向标准输出设备按规定格式输出 信息。在编写程序时经常会用到此函数。printf()函数的调用格式为:       printf("格式化字符串>", 参量表>);     其中格式化字符串包括两部分内容: 一部分是正常字符,  这些字符将按原 样输出; 另一部分是格式化规定字符, 以"%"开始, 后跟一个或几个规定字符,

程序猿养成记 370

格式化字符串漏洞及利用_萌新食用

Y格式化字符串漏洞及利用前言格式化字符串漏洞 具有 任意地址读,任意地址写。固定布局 ...

蚁景网安学院 967

sprintf函数,va_list(),va_start(),va_arg(),va_end()

在上面的myFunction(6,5,4,3,2,1)函数中,函数参数列表中最后一个固定参数(5)的地址加上第一个可变参数(4)对其的偏移量就是函数的可变参数列表了(这就是va_start的实现),也就是会使ap指向4(可变参数列表的第一个参数)。当调用此函数myFunction(6,5,4,3,2,1)时,参数入栈顺序为:1、2、3、4、5、6 参数出栈顺序为6、5、4、3、2、1. 栈底为高地址,栈顶为低地址。//串口发送字符数组(字符串)它在可变参数函数的末尾使用,以结束可变参数的处理。

m0_66078137的博客 2058

读书笔记2--C Primer Plus:字符串和格式化IO

就是一个或多个字符的序列,比如"Zing went the strings of my heart!",其中这里的双引号不算进去,它只是用来告诉编译器,里面的内容是字符串,是一种语法规范,从而能让C编译器识别处理。字符串不是C中的基本数据类型(上一节已经详细讲述过基本类型),那么C处理的方法是使用来存储,如下图所示:数组末尾的’\0’字符是空字符NULL,是ASCII码中的非打印字符,码值为0,用于标记字符串的结束。

XIAOXVPAIDAXING的博客 1849
上一篇: LTE网络协议栈
下一篇: 通信模块/组
给点sun,就shine
博客等级 码龄10年 148粉丝 112原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值