C语言printf函数详解..

1.printf函数解析

前面我们有讲过printf函数的格式为:
printf(“占位1 占位2 占位3……”, 替代1, 替代2, 替代3……);
今天我们进一步深入的解析一下这个函数

2.printf函数的特点

1.printf函数是一个变参函数(即参数的数量和类型都不确定)
2.printf函数的第一个参数是字符串
3.printf函数的第一个字符串参数中的具体内容就是需要打印的字符以及需要被替代的占位符
4.printf函数第一个参数之后的参数依次替代占位符
5.printf函数中占位和替代的数量和类型对应

3.变参函数

int main(){printf("%c\n", 'a');// aprintf("%c %d\n", 'b', 10);// b 10return 0;
}

4.第一个参数必须是字符串

int main(){printf("the first argument must be string\n");return 0;
}

5.第一个参数包含输出字符以及占位符

int main(){printf("the first argument includes %s and %s\n", "character", "placeholder");return 0;
}

后续的两个特点我就不一一阐述了

2.整型占位符

1.有符号整型的类型提升

在C语言中 有符号整型遵循一元数字提升的原则 即比int类型小的类型诸如char和short类型的一元数字都会自动提升为int类型
下面这段代码中 char类型的字节原本为1 但是由于进行了一元数字提升 导致变成了int类型 所以打印的结果是为4

int main(){char a = 'a';printf("%zu\n", sizeof(+a));// 4return 0;
}

但是还有一个疑问 就是在visual studio中 long和int类型占用的字节数是一致的 既然这些小于等于int类型的类型都使用%d作为占位符的话 那么long这种等于int的类型适合使用%d作为占位符吗 其实是不妥当的
因为前面讲过C标准没有明确规定类型占用的字节数 所以不同的平台和编译器有着自己的标准 long类型占用的字节数在不同平台和编译器下是不尽相同的
为了体现程序的可移植性 防止代码打印结果产生偏差 我们对于long类型的占位符尽量使用%ld

int main(){long l = 11;printf("%ld\n", l);return 0;
}

2.无符号整型的类型提升

其实他也同有符号整型的类型提升一样遵循一元数字提升 只不过区别在于说无符号整型涵盖的范围就是无符号的整数 而有符号整型涵盖的范围就是有符号的整数
说白了就是 比unsigned int小的无符号整型会自动提升为unsigned int类型 诸如unsigned char、unsigned short在内的一元数字会自动提升为unsigned int类型
下面这段代码可以体现无符号整型的一元数字提升

int main(){unsigned char ch = 'a';printf("%zu\n", sizeof(+ch));// 4return 0;
}

下面这段代码则体现了无符号整型的占位符

int main(){unsigned char ch = 'a';unsigned int i = 11;unsigned long l = 11;unsigned long long ll = 11;printf("%u %u %lu %llu\n", ch, i, l, ll);return 0;
}

3.转换规范

其实占位符这种说法并不准确 较为准确的说法是转换规范 我们称%d这种形式的叫做转换规范
我可以就此举一个例子:% -#0 12 .4 l d
我们可以发现真正的转换规范包含了很多东西 不仅仅是一个字母

1.转换规范的组成

转换规范以%开头 然后依次跟着以下这些元素:
1.零个或者多个标志字符 比如:- # 0
2.一个可选的十进制整型常量表示的最小字符宽度
3.一个可选的.开头的精度 后跟十进制整形常量
4.一个可选的长度指示符
5.一个字符包含的转换操作 诸如:d u f这些字符

2.转换操作

转换操作会根据不同的转换方式 截取n个字节的二进制数据 转换成不同类型的字符或者字符串
在这里插入图片描述
我们从中就可以解释前面的一个疑惑:
double和float类型都可以使用占位符%f 原因在于%f是截取sizeof(double)字节的二进制数据 然后转换为双精度浮点型的字符

1.转换操作d

对于char、short类型的整型来说 通过转换操作d是可以被正确打印的 但是对于long或者long long类型来说 由于他们可能存在int类型范围之外的数据 所以通过这个转换操作显然是不能够被正确打印的 所以对于这种比int大的整型来说 采用他们各自相应的转换操作才是最合适的做法

int main(){char c1 = 127;// char类型的最大数据short s1 = 32767;// short类型的最大数据char c2 = -128;// char类型的最小数据short s2 = -32768;// short类型的最小数据long long ll1 = 2200000000;// 超出int类型范围的数据long long ll2 = 2100000000;// 包含在int类型范围的数据printf("%d\n", c1);// 127printf("%d\n", s1);// 32767printf("%d\n", c2);// -128printf("%d\n", s2);// -32767printf("%d\n", ll1);// -2094967296printf("%d\n", ll2);// 2100000000return 0;
}

2.转换操作u

int main(){unsigned char c1 = 255;// unsigned char的最大数据unsigned short s1 = 65535;// unsigned short的最大数据unsigned char c2 = 0;// unsigned char的最小数据unsigned short s2 = 0;// unsigned short的最小数据unsigned long long ll1 = 4294967295;// unsigned long long类型中包含在unsigned int类型中的数据unsigned long long ll2 = 4300000000;// unsigned long long类型中不包含在unsigned int类型中的数据printf("%u\n", c1);// 255printf("%u\n", s1);// 65536printf("%u\n", c2);// 0printf("%u\n", s2);// 0printf("%u\n", ll1);// 4294967295printf("%u\n", ll2);// 5032704return 0;
}

3.转换操作d和u的错误搭配

由于有符号int和无符号int的取值范围不一致 导致当我们错误搭配他们的时候 可能会产生不符合预期的结果
如果当错误搭配时 数据处于两者的共同范围之内 那么打印结果符合预期
但是如果不处于两者的共同范围之内的话 那么打印的结果就不符合预期

int main(){unsigned int u1 = 2100000000;// 该数据处于有符号int和无符号int的共同范围之内unsigned int u2 = 2200000000;// 该数据并不处于两者的共同范围之内printf("%d\n", u1);// 2100000000printf("%d\n", u2);// -2094967296return 0;
}

4.注意数据类型的取值范围

如果数据超出了类型本身的取值范围 那么无论如何打印 都无法获取正确结果

int main(){char ch = 200;// 200超出了char类型本身的数据范围 -128~127printf("%d\n", ch);// -56return 0;
}

5.转换操作c

打印ASCII码表中数值对应的字符

int main(){char ch = 65;short s = 66;int i = 67;long l = 68;long long ll = 69;printf("%c %c %c %c %c\n", ch, s, i, l, ll);return 0;
}

6.转换操作f、e、E

截取sizeof(double)个字节的二进制数据 然后转换为双精度浮点型的字符

int main(){float f = 12.34;double d = 12.34;printf("%f\n", f);// 12.34printf("%f\n", d);// 12.34printf("%e\n", f);// 1.234000e+01printf("%E\n", f);// 1.234000e+01return 0;
}

7.转换操作o、x、X

截取sizeof(int)个字节的二进制数据 然后将其转换为无符号八进制、十六进制形式整数的字符

int main(){unsigned int i = 20;printf("%u %o %x %X", i, i, i, i);// 20 24 14 14return 0;
}

8.转换操作s

截取sizeof(char*)个字节的二进制数据 即地址值占用的字节数 接着以这个地址开始输出字符串

int main(){printf("%s\n", "Hello World!");return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/679461.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用 FFmpeg 将视频转换为 GIF 动画的技巧

使用 FFmpeg 将视频转换为 GIF 动画 FFmpeg 可以将视频转换为 GIF 动画,方法如下: 1. 准备工作 确保您已经安装了 FFmpeg。 熟悉 FFmpeg 的命令行使用。 了解 GIF 动画的基本知识。 2. 基本命令 ffmpeg -i input.mp4 output.gif 3. 参数说明 -i in…

JPEG图像格式加速神经网络训练--使用DCT训练CNN

JPEG图像格式加速神经网络训练 JPEG图像格式加速神经网络训练工作原理DCT系数与JPEG直接利用DCT系数阶段 1: 数据准备步骤 1: 读取JPEG文件结构步骤 2: 提取量化表和Huffman表步骤 3: 解析图像数据步骤 4: 反量化步骤 5: 获取DCT系数 阶段 2: 输入处理预处理 1: 正规化&#xf…

bert-vits2本地部署报错疑难问题汇总

环境: bert-vits2.3 win 和wsl 问题描述: bert-vits2本地部署报错疑难问题汇总 解决方案: 问题1: Conda安装requirements里面依赖出现ERROR: No matching distribution found for opencc1.1.6 解决方法 需要在 Python 3.11 上使用 Op…

巴尔加瓦算法图解:算法运用(上)

目录 树反向索引傅立叶变换 并行算法MapReduce函数 树 如果能将用户名插入到数组的正确位置就好了,这样就无需在插入后再排序。为此,有人设计了一种名为二叉查找树(binary search tree)的数据结构。 每个node的children 都不大于两个。对于其中的每个…

openGauss学习笔记-217 openGauss性能调优-确定性能调优范围-硬件瓶颈点分析-内存

文章目录 openGauss学习笔记-217 openGauss性能调优-确定性能调优范围-硬件瓶颈点分析-内存217.1 查看内存状况217.2 性能参数分析 openGauss学习笔记-217 openGauss性能调优-确定性能调优范围-硬件瓶颈点分析-内存 获取openGauss节点的CPU、内存、I/O和网络资源使用情况&…

怎么把视频音乐提取成mp3?分享详细工具和方法!

在数字媒体时代,音乐已经成为我们生活中不可或缺的一部分。有时候,我们会在社交媒体、视频分享网站或在线视频平台上看到一些非常喜欢的视频音乐,想要将其保存为MP3格式以便随时随地聆听。那么,如何从视频中提取音乐并转换为MP3格…

python+flask+django医院预约挂号系统6nrhh

医院预约挂号系统主要有管理员、用户和医生三个功能模块。以下将对这三个功能的作用进行详细的剖析。 技术栈 后端:python 前端:vue.jselementui 框架:django/flask Python版本:python3.7 数据库:mysql5.7 数据库工具…

【Spring框架】Spring事务同步

目录 一、什么是Spring事务同步 二、 事务同步管理器 2.1 TransactionSynchronizationManager事务同步管理器 2.1.1 资源同步 2.1.2 事务同步 2.1.3 总结 三、事务同步管理器保障事务的原理 四、spring事务为何使用TransactionSynchronizationManager spring源码实现 …

第二十七天| 39. 组合总和 、40.组合总和II、131.分割回文串

Leetcode 39. 组合总和 题目链接:39 组合总和 题干:给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序…

【网络】:序列化和反序列化

序列化和反序列化 一.json库 二.简单使用json库 前面已经讲过TCP和UDP,也写过代码能够进行双方的通信了,那么有没有可能这种通信是不安全的呢?如果直接通信,可能会被底层捕捉;可能由于网络问题,一方只接收到…

JavaScript中的for循环和map方法

JavaScript中的for循环和map方法 在JavaScript中,循环是一种常见的编程技巧,用于重复执行一段代码。for循环和map方法都可以用于循环操作,但它们在语法和应用场景上存在一些区别。本文将详细讲解JavaScript中的for循环和map方法,以…

【Linux技术宝典】Linux入门:揭开Linux的神秘面纱

文章目录 官网Linux 环境的搭建方式一、什么是Linux?二、Linux的起源与发展三、Linux的核心组件四、Linux企业应用现状五、Linux的发行版本六、为什么选择Linux?七、总结 Linux,一个在全球范围内广泛应用的开源操作系统,近年来越来…

神经网络(Nature Network)

最近接触目标检测较多,再此对最基本的神经网络知识进行补充,本博客适合想入门人工智能、其含有线性代数及高等数学基础的人群观看 1.构成 由输入层、隐藏层、输出层、激活函数、损失函数组成。 输入层:接收原始数据隐藏层:进行…

Stable Diffusion 模型下载:Disney Pixar Cartoon Type B(迪士尼皮克斯动画片B类)

本文收录于《AI绘画从入门到精通》专栏,专栏总目录:点这里。 文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八案例九案例十

阿里云服务器带宽计费模式是什么?怎么选择?

阿里云服务器带宽计费模式分为“按固定带宽”和“按使用流量”,有什么区别?按固定带宽是指直接购买多少M带宽,比如1M、5M、10M、100M等,阿里云直接分配用户所购买的带宽值,根据带宽大小先付费再使用;按使用…

Windows Server 2019 搭建并加入域

系列文章目录 目录 系列文章目录 文章目录 前言 一、域是什么? 二、配置服务器 1.实验环境搭建 1)实验服务器配置和客户端 2)实验环境 2.服务器配置 账户是域服务器的账户和密码 文章目录 Windows Server 2003 Web服务器搭建Windows Server 2003 FTP服务器搭…

Hadoop:认识MapReduce

MapReduce是一个用于处理大数据集的编程模型和算法框架。其优势在于能够处理大量的数据,通过并行化来加速计算过程。它适用于那些可以分解为多个独立子任务的计算密集型作业,如文本处理、数据分析和大规模数据集的聚合等。然而,MapReduce也有…

《UE5_C++多人TPS完整教程》学习笔记4 ——《P5 局域网连接(LAN Connection)》

本文为B站系列教学视频 《UE5_C多人TPS完整教程》 —— 《P5 局域网连接(LAN Connection)》 的学习笔记,该系列教学视频为 Udemy 课程 《Unreal Engine 5 C Multiplayer Shooter》 的中文字幕翻译版,UP主(也是译者&…

Java 学习和实践笔记(6)

各数据类型所占的空间: byte: 1个字节 short:2个字节 int:4个 long:8个 float:4个 double: 8个 char:1个 boolean:1bit 所有引用数据类型都是4个字节,实际其值是指向该数据类型的地址。 上图中稍特…

blender怎么保存窗口布局,怎么设置默认输出文件夹

进行窗口布局大家都会,按照自己喜好来就行了,设置输出文件夹如图 这些其实都简单。关键问题在于,自己调好了窗口布局,或者设置好了输出文件夹之后,怎么能让blender下次启动的时候呈现出自己设置好的窗口布局&#xff…