导航:首页 > 源码编译 > 使用printf进行编译的实验步骤

使用printf进行编译的实验步骤

发布时间:2022-10-03 08:47:31

❶ C++中printf() 使用方法

C++中printf() 使用

printf()函数是格式化输出函数, 一般用于向标准输出设备按规定格式输出 信息。在编写程序时经常会用到此函数。printf()函数的调用格式为:

printf("<格式化字符串>", <参量表>);

其中格式化字符串包括两部分内容: 一部分是正常字符, 这些字符将按原 样输出; 另一部分是格式化规定字符, 以"%"开始, 后跟一个或几个规定字符, 用来确定输出内容格式。

参量表是需要输出的一系列参数, 其个数必须与格式化字符串所说明的输出 参数个数一样多, 各参数之间用","分开, 且顺序一一对应, 否则将会出现意想不到的错误。

❷ 怎么在51里使用printf重定义

您的意思使用 printf 输出对吧

使用printf实现串口发送的重定义步骤:
1、首先要配置好串口的功能,以我们的第四个实验myUART_LED为例,这个工程的串口
发送已经能够实现,我们需要用printf("error,theinputnumbermustbetween1~4. ");代替Main函数中的语句:
while(TxCounter<TxBufferSize){USART_SendData(USART1,TxBuffer[TxCounter++]);//从串口1发送数据while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET){}
//等待一个发送完一个数据
}
2、在main.c文件的开头增加语句:#include"stdio.h",这样我们的程序就可以使用标准的
输入输出函数了
3、在main.c中添加函数://重定义printf到串口//intfputc(intch,FILE*f){
USART_SendData(USART1,ch);
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET){}
returnch;}
4、修改u8TxBuffer[]={"error,theinputnumbermustbetween1~4. "};
charTxBuffer[]={"error,theinputnumbermustbetween1~4. "};
(这关系到printf函数参数类型匹配的问题,如果不修改会出现一个警告)然后将Main函数中的语句:
while(TxCounter<TxBufferSize){USART_SendData(USART1,TxBuffer[TxCounter++]);//从串口1发送数据while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET){}
//等待一个发送完一个数据
}改为:
printf(TxBuffer);5、编译下载运行
说明:
fputc属于输出函数,在C语言中,包含在文件stdio.h中,为ANSI标准的函数。在步
骤3中,我们修改此函数输出设备为串口。
经重定义后,main函数就可以使用printf实现串口发送了。(大家暂且理解printf会调用
到fputc函数)。
与fputc对应的intfgetc(FILE*f);为输入函数,如果想用fgetc实现串口接收功能请按照上面例子重定义。

❸ c语言中printf的用法

c语言中printf的用法的用法你知道吗?下面我就跟你们详细介绍下c语言中printf的用法的用法,希望对你们有用。

c语言中printf的用法的用法如下:

Printf和Scan函数的使用方法

一 printf()函数是格式化输出函数, 一般用于向标准输出设备按规定格式输出

信息。在编写程序时经常会用到此函数。printf()函数的调用格式为:

printf("<格式化字符串>", <参量表>);

其中格式化字符串包括两部分内容: 一部分是正常字符, 这些字符将按原

样输出; 另一部分是格式化规定字符, 以"%"开始, 后跟一个或几个规定字符,

用来确定输出内容格式。

参量表是需要输出的一系列参数, 其个数必须与格式化字符串所说明的输出

参数个数一样多, 各参数之间用","分开, 且顺序一一对应, 否则将会出现意想

不到的错误。

格式化字符串的格式是:

%[标志][输出最小宽度][.精度][长度]格式字符

1. 标志:标志字符为-、+、#、空格四种,其意义下表所示:

标志 意义

- 结果左对齐,右边填空格

+ 输出符号(正号或负号)

空格 输出值为正时冠以空格,为负时冠以负号

# 对c,s,d,u类无影响;对o类,在输出时加前缀o;对x类,在输出时加前缀0x;对e,g,f 类当结果有小数 时才给出小数点(??????)

例1:

#i nclude

main()

{

int a=100;

float b=123.255;

printf("a=%d ",a);

printf("a=d ",a);

printf("a=%-10d ",a);

printf("a=%+d ",a);

printf("a=% d ",a);

printf("a=%#o ",a);

printf("a=%#x ",a);

printf("b=%#f ",b);

}

运行结果

a=100

a= 100

a=100

a=+100

a= 100

a=0144

a=0x64

b=123.254997 (?????)

2.输出最小宽度:用十进制整数来表示输出的最少位数。(至少要输出这么多位!)

若实际位数多于定义的宽度:则按实际位数输出。

若实际位数少于定义的宽度:则右对齐,左边留空。

有负号,左对齐,右边留空

表示宽度的数字以0开始,则右对齐,左边留空。

例2 #i nclude

main()

{

int a=3456;

printf("a== ",a); //若实际位数多于定义的宽度:则按实际位数输出

printf("a=d ",a); //若实际位数少于定义的宽度:则右对齐,左边留空

printf("a=%-10d ",a); //若实际位数少于定义的宽度:有负号,左对齐,右边留空

printf("a=0d ",a); //若实际位数少于定义的宽度:表示宽度的数字以0开始,则右对齐,左边留空

printf("a=%-010d ",a); //左对齐,0无意义。

}

运行结果:

a=3456

a= 3456

a=3456

a=0000003456

a=3456

3.精度:精度格式符以“.”开头,后跟十进制整数。意义是:

如果输出数字,则表示小数的位数;若实际位数大于所定义的精度数,则四舍五入。若不足则补0;

如果输出的是字符,则表示输出字符的个数;若实际位数大于所定义的精度数,则截去超过的部分。

例3:

#i nclude

main()

{

printf("%.3f ",12.3456);

printf("%.9f ",12.3456);

printf("%.3s ","abcdefg");

printf("%.9s ","abcdefg");

}

运行结果:

12.346 //四舍五入到小数点后三位

12.345600000 //不足补0

abc

abcdefg

4.长度:长度格式符为h,l两种,h表示按短整型量输出,l表示按长整型量输出?????

5.Turbo C2.0提供的格式字符如下:

━━━━━━━━━━━━━━━━━━━━━━━━━━

符号 作用

──────────────────────────

%c 单个字符

%d 十进制有符号整数

%e 以“科学记数法”的形式输出十进制的浮点数 如2.451e+02

%f 输出十进制浮点数,不带域宽时,保留6位小数

%g 选用e或f格式中较短的一个输出十进制浮点数,不输出无效零

%0 无输出无符号八进制整数

%p 指针的值

%s 输出字符串

%u 输出无符号十进制整数

%x, %X 输出无符号十六进制整数 (不输出前缀Ox)

━━━━━━━━━━━━━━━━━━━━━━━━━━

2. 一些特殊规定字符

━━━━━━━━━━━━━━━━━━━━━━━━━━

字符 作用

──────────────────────────

换行

f 清屏并换页

回车

Tab符

xhh 表示一个ASCII码用16进表示,

其中hh是1到2个16进制数

━━━━━━━━━━━━━━━━━━━━━━━━━━

使用这些转义字符时不需要加上%,可单独使用!

由本节所学的printf()函数, 并结合上一节学习的数据类型, 编制下面的程

序, 以加深对Turbo C2.0数据类型的了解。

例1

#i nclude

#i nclude

int main()

{

char c, s[20], *p;

int a=1234, *i;

float f=3.141592653589;

double x=0.12345678987654321;

p="How do you do";

strcpy(s, "Hello, Comrade");

*i=12;

c='x41';

printf("a=%d ", a);

printf("a=m ", a);

printf("a=d ", a);

printf("a=- ", a);

printf("*i=M ", *i);

printf("*i=%-4d ", *i);

printf("i=%p ", i);

printf("f=%f ", f);

printf("f=6.4f ", f);

printf("x=%lf ", x);

printf("x=.16lf ", x);

printf("c=%c ", c);

printf("c=%x ", c);

printf("s[]=%s ", s);

printf("s[]=%6.9s ", s);

printf("s=%p ", s);

printf("*p=%s ", p);

printf("p=%p ", p);

getch();

retunr 0;

}

其他需要注意的一些问题:

1.如果用浮点数表示字符或整型量的输出格式, 小数点后的数字代表最大宽度,

小数点前的数字代表最小宽度。

例如: %6.9s 表示显示一个长度不小于6且不大于9的字符串。若大于9, 则第9个字符以后的内容将被删除。

2.使用printf函数时还要注意一个问题,那就是输出表列中的求值顺序。不同的编译系统不一定相同,可以从左到右,也可从右到左。Turbo C是按从右到左进行的。请看下面两个例子:

例1

main(){

int i=8;

printf("%d %d %d %d %d %d ",++i,--i,i++,i--,-i++,-i--);

}

运行结果

8

7

7

8

-7

-8

例2

main(){

int i=8;

printf("%d ",++i);

printf("%d ",--i);

printf("%d ",i++);

printf("%d ",i--);

printf("%d ",-i++);

printf("%d ",-i--);

}

运行结果:

9

8

8

9

-8

-9

这两个程序的区别是用一个printf语句和多个printf 语句输出。但从结果可以看出是不同的。为什么结果会不同呢?就是因为printf函数对输出表中各量求值的顺序是自右至左进行的。在第一例中,先对最后一项“-i--”求值,结果为-8,然后i自减1后为7。 再对“-i++”项求值得-7,然后i自增1后为8。再对“i--”项求值得8,然后i再自减1后为7。再求“i++”项得7,然后i再自增1后为8。 再求“--i”项,i先自减1后输出,输出值为7。 最后才求输出表列中的第一项“++i”,此时i自增1后输出8。

但是必须注意,求值顺序虽是自右至左,但是输出顺序还是从左至右,因此得到的结果是上述输出结果。

补充:最近在调试程序时发现一段代码如下:

printf(sFormat,"%%0?",THE_NUMBER_LEN);

输出数组后发现sFormat = d;其中宏THE_NUMBER_LEN定义的为4,发现如果需要通过在printf转化的数组中出现%,那么就使用%%来代替,且后面的所有字符都会直接放入sFormat数组中一直遇到新的%。只有碰到“%+特定字符”,才会把右边对应的变量放入进来。

例如: printf(sFormat,"ABC%%d%d%%s?bc",THE_NUMBER_LEN,6);输出为ABC?%s6abc;

还有就是发现如果是修改成%0?,输出的字符串就变成 ?,这样我猜想就是在printf函数时,碰到第一个%0后知道再遇见下一个%前,如果中间没有特定字符d,s,e,f等,通通变成空格,而我在%中间增加两个的非特殊字符后,发现?前面的空格急剧增加,原因就不清楚。故两%之间不能增加其他非特殊字符。

二 Scan函数

scanf()函数是格式化输入函数, 它从标准输入设备(键盘) 读取输入的信息。

其调用格式为:

scanf("<格式化字符串>", <地址表>);

格式化字符串包括以下三类不同的字符;

1. 格式化说明符: 格式化说明符与printf()函数中的格式说明符基本相同。

2. 空白字符: 空白字符会使scanf()函数在读操作中略去输入中的一个或多

个空白字符。

3. 非空白字符: 一个非空白字符会使scanf()函数在读入时剔除掉与这个非

空白字符相同的字符。

注意:(1)地址表是需要读入的所有变量的地址, 而不是变量本身:

----如果是一般的变量,通常要在变量名前加上"&";但输出时是用变量名

----如果是数组,用数组名就代表了该数组的首地址;输出时也是用数组名

----如果是指针,直接用指针名本身,不要加上“*”;输出时也用该指针即可。

例1:

各个变量的地址之间同","分开。

main()

{

int i;

char *p, str[20];

scanf("%d", &i);

scanf("%s", p);

scanf("%s", str);

printf("i=%d ",i);

printf("%s ", p);

printf("%s ", str);

}

(2)scanf函数中是否包含空白/非空白字符导致输入格式的不同

如:scanf("%d,%d",&i,&j); scanf中有,所以输入的格式应该是5,6==>i=5,j=6

scanf("%d%d",&i,&j); 可以用空格或回车来分隔两个输入 如 5 6==>i=5,j=6

scanf("%d %d",&i,&j); 同上

(3) 实际使用scanf()函数时存在一个问题, 下面举例进行说明:

当使用多个scanf()函数连续给多个字符变量输入时, 例如:

main()

{

char c1, c2;

scanf("%c", &c1);

scanf("%c", &c2);

printf("c1 is %c, c2 is %c", c21, c2);

}

运行该程序, 输入一个字符A后回车 (要完成输入必须回车), 在执行scanf

("%c", &c1)时, 给变量c1赋值"A", 但回车符仍然留在缓冲区内, 执行输入语句

scanf("%c", &c2)时, 变量c2输出的是一空行, 如果输入AB后回车, 那么输出结

果为: c1 is A, c2 is B。

要解决以上问题, 可以在输入函数前加入清除函数fflush()( 这个函数的使

用方法将在本节最后讲述)。修改以上程序变成:

#i nclude

main()

{

char c1, c2;

scanf("%c", &c1);

fflush(stdin);

scanf("%c", &c2);

printf("c1 is %c, c2 is %c", c1, c2);

}

在输入字符数据时,若格式控制串中无非格式字符,则认为所有输入的字符均为有效字符。

例如:scanf("%c%c%c",&a,&b,&c);

输入为:d e f

则把'd'赋予a, ' ' 赋予b,'e'赋予c。

只有当输入为: def

时,才能把'd'赋于a,'e'赋予b,'f'赋予c。

如果在格式控制中加入空格作为间隔,

如:scanf ("%c %c %c",&a,&b,&c);

则输入时各数据之间可加空格。

例4

main(){

char a,b;

printf("input character a,b ");

scanf("%c%c",&a,&b);

printf("%c%c ",a,b);

}

由于scanf函数"%c%c"中没有空格,输入M N,结果输出只有M。而输入改为MN时则可输出MN两字符。

(4)格式字符串的一般形式为:

%

[输入数据宽度][长度]类型

其中有方括号[]的项为任选项。各项的意义如下:

1)类型:表示输入数据的类型,其格式符和意义如下表所示。

格式 字符意义

d 输入十进制整数

o 输入八进制整数

x 输入十六进制整数

u 输入无符号十进制整数

f或e 输入实型数(用小数形式或指数形式)

c 输入单个字符

s 输入字符串

2)“*”符:用以表示该输入项,读入后不赋予相应的变量,即跳过该输入值。

如:scanf("%d %*d %d",&a,&b);

当输入为:1 2 3时,把1赋予a,2被跳过,3赋予b。

3)宽度:用十进制整数指定输入的宽度(即字符数)。

例如:

scanf("]",&a);

输入:12345678

只把12345赋予变量a,其余部分被截去。

又如:scanf("MM",&a,&b);

输入:12345678

将把1234赋予a,而把5678赋予b。

例:

main()

{

int a,b;

scanf("MM",&a,&b);

printf("a=%d,b=%d",a,b);

}

输入 12345 67890

运行结果 a=1234,b=5

4) 长度:长度格式符为l和h,l表示输入长整型数据(如%ld) 和双精度浮点数(如%lf)。h表示输入短整型数据。

使用scanf函数还必须注意以下几点:

1)scanf函数中没有精度控制,如:scanf("%5.2f",&a);是非法的。不能企图用此语句输入小数为2位的实数。

2)在输入多个数值数据时,若格式控制串中没有非格式字符作输入数据之间的间隔则可用空格,TAB或回车作间隔。C编译在碰到空格,TAB,回车或非法数据(如对“%d”输入“12A”时,A即为非法数据)时即认为该数据结束。

❹ 各位百度大神们,在keil uv3环境下编译lpc2000系列程序,应该如何使用printf()函数

我来给你解答吧。
看你的printf语句的终端是指向哪里了,可能是串口也可能只是你keil里边的一个虚拟终端。
这俩差不多,keil的虚拟终端也是模拟的串口的
首先需要包含stdio.h
然后需要显示实现一个函数,重新定义一个fput函数,该函数是ANSI标准的,在这个函数里边的实现的是发送一个字符到串口。然后以此函数为基础的printf就可以用了。详细的步骤,请查查“标准输出函数的重定义”。

❺ c程序的运行环境和运行一个c程序的方法实验报告书

实验目的 (1)了解所用的计算机系统的基础操作方法,学会独立使用该系统。 (2)了解在该系统上如何编辑、编译、连接和运行一个C程序。 (3)通过运行简单的C程序,初步了解C源程序的特点。 二、实验内容 1.检查所用的计算机系统是否已安装了C编译系统并确定它所在的子目录。如果是在Windows操作系统下使用Turbo C编译器,可以按以下步骤进行操作: ①单击Windows桌面上的“开始”按钮,在菜单中单击“查找(F)”,在其右面的下拉菜单中单击“文件或文件夹(F)”。屏幕上出现“查找”窗口。 ②在“名称”框中输入文件名“tc.exe”,单击“开始查找”按钮,系统即自动在指定的范围内寻找所需要文件,如果找到,就会显示出文件路径(例如:C:\lib\tc或c:\tc)。 ③注意:在“搜索”框中应说明搜索范围,如使“搜索”栏中的内容为“C:\”,表示从根目录开始寻找,即搜索整个C盘。 2.建立用户自己的子目录 ①利用“Windows资源管理器”在磁盘(如D盘)上建立自已的文件夹。 ②利用DOS命令md在磁盘上建立自己的子目录。 3.进入TC工作环境 第一种方法; ①单击桌面上的“开始”按钮,从菜单中选择“程序”,单击它然后在其下拉菜单中选择“MS-DOS”,屏幕上出现MS-DOS窗口。 ②用DOS命令cd,使当前目录改变为tc.exe所在的子目录(例如:C:\lib\tc)。 ③在tc的子目录下输入tc,按回车键进入tc的工作环境。 第二种方法: 用鼠标双击“我的电脑”图标,进入C盘根目录,在C盘根目录下找到tc.exe文件所在的文件夹(如C盘下的lib文件夹下的tc文件夹),在文件夹中找到tc.exe文件,双击鼠标进入TC的工作环境。 4.熟悉Turbo C集成环境 ①了解和熟悉编辑(Edit)窗口和信息(Message)窗口的作用。试一下能否向信息窗口输入程序。按功能键F5,观察它有什么作用,再按一次F5,再观察它有什么作用。按F6,观察它有什么作用;再按一次F6,再观察它有什么作用。(参见第一部分的1.1节) ②按功能键F10,并按回车键,观察“File”菜单,了解它们的作用和方法。用键盘上的“→”键,分别选中Edit、Run、Compile、Project、Options、Debug、Break/watch,观察它们的菜单,大致上了解它们的作用,以后用到时再深入了解。 ③选择File菜单中的New并按回车键,在编辑窗口中随意输入几行字符,观察窗口顶部左端line和col后面数字的变化。 5.编辑并运行一个简单的程序 ①再选择File菜单中的New并按回车键,使编辑窗口变成空白。 ②输入下面的程序 main( ) { printf("* * * * *\n"); printf(" Hello.\n"); printf("* * * * *\n"); } ③按功能键F9进行编译和连接,观察屏幕上显示的编译信息。如果出现“出错信息”,则应找出原因并改正之,再进行编译。 ④如果编译无错误,按Ctrl和F9键使程序运行,按Alt和F5键,切换到用户屏,观察运行结果。 ⑤按任一键回到TC窗口,将程序命令为ex1.c保存在自已的子目录下。(参见第一部分1.2节的内容) 6.编辑并运行另一个C程序 ①再选择File→New,使编辑窗口变成空白。 ②输入以下程序 main( ) { int a,b,sum; a=150;b=200; sum=a+b; printf("sum is %d\n",sum); } ③按F9进行编译,仔细分析编译信息窗口和Message窗口,可能显示有多个错误,逐个修改,直到不出现错误。 ④运行程序,分析运行结果。 ⑤将程序命名为ex2.c,保存到自己所建的子目录下。 7.编辑并运行一个需要在运行时输入数据的程序 ①清空编辑窗口,输入下面的程序。 main( ) { int a,b, max; scanf("%d%d",&a,&b); if(a>b) max=a; else max=b; printf("%d",max); } ②编辑并运行,注意按Ctrl和F9运行后,先从键盘输入整数2和5,然后按回车键,再按Alt和F5键,观察运行结果。 ③将程序中的第3行改为: int a;b;max; 再进行编译,观察其结果。 ④将程序第5、6两行合并为一行,即 if(a>b) max=a ; else max=b ; 进行编译和运行,分析结果。 将程序命名为ex3.c保存在用户自己的子目录下。

麻烦采纳,谢谢!

❻ c语言里怎么使用printf

printf()函数是格式化输出函数,调用格式为: printf("<格式化字符串>", <参量表>)。

scanf()函数是格式化输出函数,调用格式为:scanf("<格式化字符串>", <参量表>)。

格式输出,它是c语言中产生格式化输出的函数(在 stdio.h 中定义)。用于向终端(显示器、控制台等)输出字符。格式控制由要输出的文字和数据格式说明组成。要输出的的文字除了可以使用字母、数字、空格和一些数字符号以外,还可以使用一些转义字符表示特殊的含义。

(6)使用printf进行编译的实验步骤扩展阅读

C语言是一门通用计算机编程语言,广泛应用于底层开发。C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。

尽管C语言提供了许多低级处理的功能,但仍然保持着良好跨平台的特性,以一个标准规格写出的C语言程序可在许多电脑平台上进行编译,甚至包含一些嵌入式处理器(单片机或称MCU)以及超级电脑等作业平台。

二十世纪八十年代,为了避免各开发厂商用的C语言语法产生差异,由美国国家标准局为C语言制定了一套完整的美国国家标准语法,称为ANSI C,作为C语言最初的标准。

目前2011年12月8日,国际标准化组织(ISO)和国际电工委员会(IEC)发布的C11标准是C语言的第三个官方标准,也是C语言的最新标准,该标准更好的支持了汉字函数名和汉字标识符,一定程度上实现了汉字编程。

C语言是一门面向过程的计算机编程语言,与C++,Java等面向对象的编程语言有所不同。

其编译器主要有Clang、GCC、WIN-TC、SUBLIME、MSVC、Turbo C等。

参考资料网络-c语言

❼ printf函数的实现方式

其实printf和getchar()类似,它们都是一个”外壳“,真正实现功能的不是它本身,而是通过调用别的函数。
getchar() is equivalent to getc(stdin).
printf有一家子print函数

printf, fprintf, sprintf, snprintf, vprintf, vfprintf, vsprintf, vsnprintf - formatted output conversion
它们的声明在不同的header file里面

#include <stdio.h>

int printf(const char *format, ...);
int fprintf(FILE *stream, const char *format, ...);
int sprintf(char *str, const char *format, ...);
int snprintf(char *str, size_t size, const char *format, ...);

#include <stdarg.h>

int vprintf(const char *format, va_list ap);
int vfprintf(FILE *stream, const char *format, va_list ap);
int vsprintf(char *str, const char *format, va_list ap);
int vsnprintf(char *str, size_t size, const char *format, va_list ap);
snprintf(), vsnprintf():
这两个函数是C99新加的,编译的时候 注意 -std=c99

实现之前还是“复习”一下printf比较好,就当是铺垫
有意思的是printf的declaration。
int printf(const char *format, ...);
返回值是int,第一个参数是const字符串指针,第二个参数是个...
先看看返回值int有哪些情况
Return value
Upon successful return, these functions return the number of characters printed (excluding the null byte used to end output to strings).

嗯哼。。。返回的是成功打印的字符的个数,这里不包括NULL
demo:
#include<stdio.h>

int main()
{
int counter = 0;

counter = printf("hello world! %d\n",10);

printf("counter is %d\n",counter);

return 0;
}
jasonleaster@ubuntu:~$ ./a.out
hello world! 10
counter is 16

接着,第一个参数是一个指针,指向const字符串
Format of the format string
The format string is a character string, beginning and ending in its initial shift state, if any. The format string is composed of
zero or more directives: ordinary characters (not %), which are copied unchanged to the output stream; and conversion specifications,
each of which results in fetching zero or more subsequent arguments. Each conversion specification is introced by the character %,
and ends with a conversion specifier. In between there may be (in this order) zero or more flags, an optional minimum field width,
an optional precision and an optional length modifier.

很少人会用下面这种用法
printf("%*d",10,5);
我第一次遇到的时候,可以说是“惊愕”,究竟会打印什么东西。折腾了好久,最后搞定了。总结在这里
http://blog.csdn.net/cinmyheart/article/details/10116359

Format of the format string

The format string is a character string, beginning and ending in its initial shift state, if any. The format string is composed of zero or more directives: ordinary characters (not %), which are copied unchanged to the output stream; and conversion specifications, each of which results in fetching zero or more subsequent arguments. Each conversion specification is introced by the character %, and ends with a conversion specifier. In between there may be (in this order) zero or more flags, an optional minimum field width, an optional precision and an optional length modifier.
The arguments must correspond properly (after type promotion) with the conversion specifier. By default, the arguments are used in the order given, where each '*' and each conversion specifier asks for the next argument (and it is an error if insufficiently many arguments are given). One can also specify explicitly which argument is taken, at each place where an argument is required, by writing "%m$" instead of '%' and "*m$" instead of '*', where the decimal integer m denotes the position in the argument list of the
desired argument, indexed starting from 1. Thus,
printf("%*d", width, num);
and
printf("%2$*1$d", width, num);
are equivalent. The second style allows repeated references to the same argument. The C99 standard does not include the style using '$', which comes from the Single UNIX Specification. If the style using '$' is used, it must be used throughout for all conversions taking an argument and all width and precision arguments, but it may be mixed with "%%" formats which do not consume an argument.
There may be no gaps in the numbers of arguments specified using '$'; for example, if arguments 1 and 3 are specified, argument 2
must also be specified somewhere in the format string.

第三个参数 ...
嗯,这家伙有点屌,叫做变长参数。把这个搞定,C总会有点长进的
这个stdarg.h 我在现在的GCC和现在的linux 3.0版本的内核里面找了好久,都木有,估计是封装到被的地方了。。。。
__builtin_va_start(v,l) 线索就死在这个地方。。。之后就找不到__builtin_va_start的定义了

还是看早起内核的实现吧
0.12内核里面的stdarg.h
#ifndef _STDARG_H
#define _STDARG_H

typedef char *va_list;

/* Amount of space required in an argument list for an arg of type TYPE.
TYPE may alternatively be an expression whose type is used. */

#define __va_rounded_size(TYPE) \
(((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))

#ifndef __sparc__
#define va_start(AP, LASTARG) \
(AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))
#else
#define va_start(AP, LASTARG) \
(__builtin_saveregs (), \
AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))
#endif

void va_end (va_list); /* Defined in gnulib */
#define va_end(AP)

#define va_arg(AP, TYPE) \
(AP += __va_rounded_size (TYPE), \
*((TYPE *) (AP - __va_rounded_size (TYPE))))

#endif /* _STDARG_H */

va_list 是一个指向字符串的指针
分析上面的宏定义#define __va_rounded_size(TYPE) \
(((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))
这个用来得到TYPE元素类型的字节大小,若不足4字节(例如short 和char),那么认为这个元素的大小为4字节,简单的说就是检测元素的大小,不足4字节的当作4字节看待。。。#define va_start(AP, LASTARG) \
(AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))

AP一般都是va_list,LASTARG则是 指向参数变长函数的格式化字符串的指针.
va_start的作用就很明显了。取得变长参数列表的第一个参数的地址。
va_end 则是把指针va_list 置0 (通过google知道的,这个va_end真没找到定义,代码里面就一句#define 我无能为力啊。。。)
不过知道用va_start 和va_end 就OK啦
下面先来个变长参数的demo
/*****************************************************************************
code writer : EOF
code date : 2014.04.26
e-mail:[email protected]
code purpose:
just a demo for varible parameter function.

usage: va_sum(a number,anohter number...,0);
va_sum(1,2,3,4,5,0); return 15

******************************************************************************/

#include <stdarg.h>
#include <stdio.h>

int va_sum(int* a,...);

int main()
{
int number = 1;

int foo = 0;

foo = va_sum(&number,2,3,4,5,0);

return 0;
}

int va_sum(int* a,...)
{
int counter = 0;
int element = 0;

va_list arg;

va_start(arg,a);

while((element = va_arg(arg,int)) != 0)
{
counter += element;
}

va_end(arg);

return counter;
}

#define va_arg(AP, TYPE) \
(AP += __va_rounded_size (TYPE), \
*((TYPE *) (AP - __va_rounded_size (TYPE))))

❽ c语言printf用法

这个相当于
printf((const char *)'001');
你随意指定了一个指针,然后恰好那个地方有数据,但是没有'\0‘,所以就输出了一堆乱七八糟。
实际上也有可能会崩溃,还有可能什么都不输出。
C语言不检查参数类型,你无论写什么都当做const char * fmt。这是C语言的优点之一,也是缺陷之一。不过目前大部分编译器会发出警告,早期的编译器可能不会。

你可以这样考虑:
printf("%X\n",'001');
'001'实际上就是一个数,不同编译器略有不同。

gcc 4上面的结果是303031
printf('001');
相当于printf((const char *)0x303031);

阅读全文

与使用printf进行编译的实验步骤相关的资料

热点内容
单片机can程序 浏览:271
程序员越来越多吗 浏览:696
bb9机器人是下载什么app 浏览:48
系统资源管理器加密 浏览:954
为什么安卓的app比ios垃圾 浏览:292
安卓怎么放音乐给队友听 浏览:753
程序员吃中国美食视频 浏览:50
手机无损压缩图片 浏览:515
pdf文字重叠 浏览:658
百度钱包app现在叫什么 浏览:412
中考总分的算法 浏览:932
mc如何搭建服务器地址 浏览:109
明日之后苹果如何登录安卓的号 浏览:46
基于单片机的太阳能热水器 浏览:556
901单片机使用教程 浏览:995
曲线命令快捷 浏览:744
加密的应用怎样使用 浏览:558
文件夹怎么说英文 浏览:234
python可以按文件夹名称遍历吗 浏览:369
苏州稳健压缩机滤芯维修 浏览:788