《玩透嵌入式C的角角落落》深刻分析sprintf和printf函数

2022年01月13日 阅读数:6
这篇文章主要向大家介绍《玩透嵌入式C的角角落落》深刻分析sprintf和printf函数,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。
//只节选部分代码说明
  char txt[32];
  unsigned int Distance=0;
  while(1) 	
	{
   
   			
		if(timecount>=50)                   //500ms采集一次距离
		{
   
   
			if(CheckChanel[0]==1) 
			{
   
   
				Distance = Read_Distance();
				if(Distance<1000)
				{
   
   
				  Gui_DrawFont_GBK16(100,25,BLUE,GRAY0,"  ");			
				}		
                sprintf(txt, "%d", Distance);
		        Gui_DrawFont_GBK16(85,25,BLUE,GRAY0,txt); //前两个参数是坐标,显示内容颜色,背景色,数据		
			}
			timecount=0;
			LED1=~LED1;
		}	
	}		
}

    最近项目用到了sprintf函数调试程序,故想写下一篇博客来分析下sprintf函数,其函数原型为ios

function prototype
int sprintf(char *buffer ,const char *format, [argument]…);c++

    看到const和指针的声明,我想简单提下几种声明的区别,在经典书《C专家编程》有对恐怖的C语言声明作过解释web

/*第1,2种状况,指针所指向的对象是只读的
  固然对象和指针有可能都是只读的*/
const char *format; 
char const *format;

char * const format; //第3种状况指针是只读的

/*下面两种方式的声明都能作到这一点--->对象和指针都是只读的*/
const char * const format; 
char const * const format;

小技巧------>Keil5中鼠标放在调用函数名处不动,便可显示出该函数的函数原型编程

玩透sprintf和printf函数

  • sprintf是一个变参函数,和printf的功能差很少,只是第一个参数是指定把输出的内容输出到“什么地方数组

  •   //网友的例子
      例:将”test 1 2”写入数组s中
      #include<stdio.h>
      int main(int argc, char *avgv[])
      {
        char s[40];
        /*第一个参数就是指向要写入的那个字符串的指针,剩下的就和printf()同样了*/
        sprintf(s,"%s%d%c","test",1,'2'); 
          
       /*你能够比较一下,这是向屏幕输入*/
        printf("%s%d%c","test",1,'2');
        return 0;
      }
    

    网上找的例子是在标准C语言在PC端调试,最经常使用的printf打印函数,会直接打印到PC端命令行窗口上,而在单片机调试中,咱们经常使用printf打印有用信息来调试咱们的程序,可是却不能直接使用,究其缘由,在于标准C语言printf函数的底层实现的机制,已经规定输出流输出到PC端的显示器(或者是现编译器的命令行窗口)。svg

    这也是单片机调试时,为何要对printf函数进行重定向的缘由,所谓重定向,这里涉及流的概念,即“从新定义信息流的流动方向‘’——我从哪里来,又要到哪里去”。即要实如今串口或者LCD上显示,必须重定义标准库函数里面调用的输出设备定义的相关函数。函数

    扩展一下:在C++中,包含了标准库#include ,其中stream英文表示流的意思,iostream库是istream(输入流)和ostream(输出流)组合而成,术语流极其想表达出字符随着时间顺序生成和消失的特色。ui

	#include<iostream>
	int main(){
		std::cout<<"hello,world";
		return 0;
	}

    接下来,咱们又回到sprintf函数,sprintf在参数列表中多了一个“具体输出到什么地方”的参数。与printf函数不一样在于转化后的结果没有送往标准输出设备,而是存放在由指针变量buffer指定的字符缓冲区,这个缓冲区能够是个字符数组。
    例如,将浮点数3.14转化成长度为4,含2位小数的字符串,存储在字符缓冲区buffer中,代码以下:spa

sprintf(buffer,"%4.2f",3.14)

项目中sprintf的用法prototype

#include "stdio.h"   //为了解除sprintf警告
unsigned int Distance=0;
char txt[32];
/*这个Distance在上文环境中被定义为距离变量,
测距传感器采集的距离值存储在此变量内。*/
sprintf(txt, "%d", Distance);
//将Distance变量内容按照%d格式放在txt数组中,来方便显示

汇总sprintf三大常犯错误:
1.给定的缓冲区溢出,如给的数组的长度过短而致使溢出
2.和printf搞混,忘记第一个参数。
3.对应的格式化字符串用错,参数能够有不少个

char s[40];
sprintf(s,"%s%d%c","test",1,'2'); 
/*这里将内容("test",1,'2')按照指定的格式("%s%d%c")输出
到这个地方(s)*/

    sprintf函数功能强大,能够方便的完成各种数据类型的转换,但会占用至关大的代码空间。