c语言输出特殊值值不变

欢迎访问C语言网
比赛栏每月有奖月赛!举办比赛联系QQ:问题反馈、粉丝交流
蓝桥杯训练群:
申请群时请备注排名里的昵称C语言研究中心 为您提供有图、有料、解渴的C语言专题! 欢迎讨论!
想必大家都知道C语言中动态开辟内存之后,必须要释放内存,来防止内存泄露。也就是malloc之后,必须要free。正所谓”有借有还,再借不难”, 不少同学会问为什么释放指针后,指向这块内存的指针的值不变呢,我们今天为大家揭秘。
首先,我们用malloc开辟一个内存,用strcpy拷贝一串字符串,然后释放掉,通过断点调试进行观察!
下图可以看到,在VC6编译环境下,观察指针p的指针所指向的内容已经被strcpy后改变
下一步free函数,我们选择F11单步介入观察,幸运的是在VC6中可以看到源代码,如下图,会进入到DBGHEAP.c文件中,会调用_free_dbg函数,继续F11介入观察代码
多次单步之后,我们可以看到一个memset函数,那么F10执行这memset,观察P指向的内容,果然不出我们所料:
0x00970e38处的内容已经被0xDD覆盖,如下图红色字部分。
这里重点观察了,这个memset函数我们应该很熟悉,第二个参数即为要重置的内容,这里我们可以转到定义 处,或者搜索第二个参数_bDeadLandFill,可以看到有如下定义, 为0xDD
怎么样,大家看到这里应该明白了吧!
我们这里是VC6编译器下的环境,也有部分同学反映free之后内容并未消失,这里我们分析可能是部分编译器free函数实现原理不同,欢迎大家自行尝试,并与我们交流。
而关于free之后,p的之后为何没有改变,仍然还是这个原先堆空间的这个地址,原因在于free函数仅仅是将malloc申请的内存释放回去,所谓的释放也就是告诉编译器,这块内存已经使用完毕,可以收回了。但指针所指向的内存值,并不会发生改变。就可以比方说,你租了一套房子,到期后,房子收回归还房东,而此时你可能还拿着房子的钥匙,这个时候你虽然可以继续访问这个房子(内存),但已经不属于你,是非法的。也可能有新的租客入驻更改房子的内置,也可能还是这个样子。取决于不同的房东(编译器)和租客(内容)。
这就是free释放内存后,指针内地址仍然存在,但有时还可以访问,有时候访问输出乱码或输出其他值的原因。
怎么样,大家明白了吗?
有任何问题,或新的发现,欢迎联系我们!
C语言网, 版权所有丨如未注明 , 均为原创丨本网站采用协议进行授权 , 转载请注明!千里之行 始于足下
欢迎加入我们,一同切磋技术。 &
用户名: &&&
密 码: &
共有 6012 人关注过本帖
标题:为什么调用无返回值的函数函数还可以返回数值呢?请各位高手指点一下。
来 自:成都
等 级:新手上路
帖 子:32
结帖率:85.71%
&&已结贴√
&&问题点数:10&&回复次数:6&&&
为什么调用无返回值的函数函数还可以返回数值呢?请各位高手指点一下。
调用的明明是无返回值函数,我为什么还能实现它的功能呢?
#include &stdio.h&
void&&fun(int a[3][3],int b[3][3])
&&int i,j;
&&&&&for(i=0;i&3;i++)
&&&&&for(j=0;j&3;j++)
&&&&&&b[i][j]=a[j][i]+a[i][j];
void main()
&int a[3][3]={{1,2,3},{4,5,6},{7,8,9}};
&int t[3][3],i,j;
&fun(a,t);
&for(i=0;i&3;i++)
&&for(j=0;j&3;j++)
&&printf(&%7d&,t[i][j]);
&&printf(&\n&);
搜索更多相关主题的帖子:
等 级:黑侠
帖 子:110
专家分:670
加为在fun(a,t)中a,t其实性质跟指针是一样的……
来 自:广东潮州
等 级:小飞侠
帖 子:1182
专家分:2784
回复 楼主 康冬亮
你的调用函数是空类型的无返回值,有返回值要用return带回,你那代码中是通过对,形参数组值的改变从而对实参值的改变的目的,因为实参数组与形参数组实则是占同一存储单元的不同名字。
一步一个脚印...............................默默地前进.....
诚邀乐于解答c菜鸟问题,的热心网友加入,&&QQ群
来 自:成都
等 级:新手上路
帖 子:32
回复 3楼 A
哦&&精辟&&谢谢
等 级:新手上路
你去把指针的内容看一遍就知道为什么了,你这种不叫返回数值,实参和形参也不是占用同个存储单元,子函数一调用完形参就会释放内存。
来 自:成都
等 级:新手上路
帖 子:32
回复 5楼 linzekai
好的&&我去看&&谢谢了
等 级:论坛游民
专家分:10
因为数组参数传过去的是数组的首地址,此时形参和实参是共用相同的存储空间的,你在形参中存储单元的值给改变了,所以这边打印出来是改变后的存储单元的值
版权所有,并保留所有权利。
Powered by , Processed in 1.287902 second(s), 7 queries.
Copyright&, BCCN.NET, All Rights ReservedAccess denied |
used Cloudflare to restrict access
Please enable cookies.
What happened?
The owner of this website () has banned your access based on your browser's signature (3ccd3c-ua98).C语言数据类型和格式输出总结 - 简书
C语言数据类型和格式输出总结
1 编译型和解释型语言的区别
b平台无关性
2 gcc -E/-S/-C/-O 参数的意义
预处理:进行预处理
编译:将代码翻译成汇编语言
汇编:将汇编文件转换为二进制目标代码
链接:生成可执行文件
3 求余与除法
-7/3 = -2 因为-2*3 = -6。 -6+(-1) = -7。因此取余为-1
同理可知7%-3 = 1。
可总结出取余的正负与被除数相同
-7/3=-2 -7%3=-1
4 不用第三方变量进行数据交换
#include&stdio.h&
int mian()
int a = 10, b = 5;
printf("a = %d b = %d",a,b);
#include&stdio.h&
int mian()
int a = 10, b = 5;
printf("a = %d b = %d",a,b);
5补码。。查看书籍《编码》
个人理解:
首先要理解一个原则,数据定义后如果不去修改它的话,其在内存中是以补码的形式存在的,并且该补码数值不会更改。
unsigned int a = -1 一旦声明 -1 就以 int 型的形式将-1 的补码存储在内存中,而内存中这个值是不变的, 就看编译器如何去解读。比如,此次我们都将 -1 的补
码以unsigned int类型去解释。我们知道int 型的 -1 在内存中是以补码存储的,其补码为
如果我们以int去解释这个补码的话,该补码对应的int 值就是 -1
如果我们以unsigned int 去解释这个补码的话,该补码对应的就不是 -1了,而是二进制的 11 11
这将是很大的一个数。
因此printf("a = %u\n",a);将输出,即上面的二进制转换为十进制的值
当执行printf("a + b = %d\n",a+b);时,a + b不同类型的数据要进行运算时,会进行隐式转换,将 a 隐式转换成 int 型,即以int型去解释a,此时 a 的值即为-2。故 a + b = -2 +2 =0。因此,输出为0
#include &stdio.h&
int main(int argc, char *argv[])
unsigned int a =-1;
int b = 1;
printf("a = %u\n",a);
printf("b = %u\n",b);
printf("a + b = %d\n",a+b);
下面这条语句将输出129.因为-127在计算机中是以补码 形式存储的。将它强制转换为unsigned char,则其对应的值为129.因此%d输出为129
printf("%d\n",(unsigned char)(-127));
下面这两条语句输出结果都是
printf("%u\n",(unsigned int)(-1));
printf("%u\n",-1);
下面这两条语句都输出-1,格式化输出 , 后面表示该数据类型是什么,要从该数据的其实指针去读多少个字节。而格式化输出%d或%u等表示以什么样的形式去解读这些字节。
printf("%d\n",(unsigned int)(-1));
printf("%d\n",-1);
下面这条语句的输出为
#include&stdio.h&
int main()
int a = -129;
printf("%d\n",(unsigned int )(a));
printf("%u\n",a);
printf("\\= %d
\\ = %d",'\\','\\');//输出 \= 92
printf("\"= %d
\" = %d",'"','\"');//输出 "= 34
1 sizeof('a') printf(&%d&,sizeof('a')); 上面这条语句输出 4 。原因是 sizeof 取值时,默认把 'a' 当作 ASCII 相应的值即 97 ,等于 sizeof(97)=4 2比较浮点数和零的值的大小 首先看一下上面这段代码,这...
1.编译程序(1)gcc
xx.c,他会默认生成一个a.out的可执行文件,在a.out所在目录,执行./a.out(2)gcc xx.c -o xx,生成一个xx可执行文件,注意不要命名成xx.c,这样会覆盖原先的xx.c文件内容(3)gcc xx.c -o xx -g...
1.编译程序 (1)gcc
xx.c,他会默认生成一个a.out的可执行文件,在a.out所在目录,执行./a.out(2)gcc xx.c -o xx,生成一个xx可执行文件,注意不要命名成xx.c,这样会覆盖原先的xx.c文件内容(3)gcc xx.c -o xx -...
C语言基础 编译程序 gcc xx.c,他会默认生成a.out的可执行文件,在a.out所在目录,执行./a.outgcc xx.c -o xx,生成一个xx可执行文件,注意不要命名成xx.c,这样会覆盖原先xx.c文件内容gcc xx.c -o xx -g -Wall的意...
1、标识符 什么事标识符呢?变量的名字就是标识符。不仅限于变量名,程序中各种元素的名字,都属于标识符。例如符号常量名、函数名、数组名、类型名等。关键字也叫保留字。属于关键字的词已被系统“注册”了,特殊用途,我们在为程序中的各种元素命名时是坚决不能使用这些关键字的。 C语言中...
又到了一年一度的2月14日情人节。 我和她相识已经十年,相互陪伴走过了彼此最青涩的年纪,却没能与她共度过一个情人节。 那年,我13岁,她12岁。 她是当时班级的英语课代表,也是班里的班花,性格开朗,很多人都喜欢与她一起玩,蛮多老师也喜欢这样的女孩子。 我坐在倒数第一排,长得...
一、尝试做一个Benefit Finder,优势发现者。在作业中,写下自己对生活中10件好事情的感激之情,你可以感激自己,感激他人,也可以感激发生的所有事情。 1、我隔两天都会问男友,我有没有进步(指专业)?一般是回答没有。一次回答有,我很开心,问他我哪里进步了(以为是专业...
1.__name__是当前module名: 如果是放在Modules模块中,就表示是模块的名字 2.__main__: 模块第一次被导出(import)后,系统会自动为其创建一个域名空间(namespace);(模块,都是有自己的名字的)此处的脚本...
1 从春季的樱花飘散,到如今的蝉鸣四起,一转眼来到北京五个月了。比起许多老北漂们,我来的时间还太短。但我发现我已经爱上了这个城市。 前几日和一个姑娘约饭,已经某颇有名气公号的作者。 作者妹子比我要来得早,她已经在北京两年了,巧的是我们竟然来自同一个省份,连大学读的也是隔壁学...
他越来越好了,我慢慢回想内心无限欣喜,欢畅 不像以前,冷傲悲伤不再,无人诉衷肠但,和当年一样享受大大小小的创造怀着热情,在生活里闯感受爱,世间的美不枉生命一场 他看得见世界的复杂也懂得,我的简单信仰他更加勇敢坚定也有了更多智慧的杰作和更多知心人分享,从不私藏 想起他在黑夜里...c语言中的输入输出
我的图书馆
c语言中的输入输出
&输入字符getchar()
getchar函数是对单个字符进行输入的函数。它的功能是:从标准输入设备上(键盘)输入一个且只能是一个字符,并将该字符返回为getchar函数的值。&&&&&&格式: getchar()例如:&&&&&&&&&&&&ch = getchar(); ch为字符型变量,上述语句接收从键盘输入的一个字符并将它赋给ch。 例1:getchar函数应用。 #include &stdio.h&main(){&&&&&&&&&&&&i=getchar();&&&&&&printf("%c:%d\n",i,i); }执行本程序时,按下字符‘A’并回车后,显示结果如下:&&&&&&A:65在使用getchar函数时,要注意以下几点: 1)getchar函数是不带参数的库函数,但是()不能省略。2)用户输出一个字符后,只当按“回车”键之后输入的字符才有效; 3)getchar函数只接受一个字符,而非一串字符。上例中:若输入abcde,getchar函数也只接受第一个字符‘a’。 4)getchar函数得到的字符可以赋给一个字符变量或整型变量,也可以不赋给任何变量而是作为表达式的一部分。 5)getchar函数不能够显示输入的数据,如果希望显示该数据,必须调用相应的输出函数(例如putchar()库函数)来实现。 还有一个与之相接近的函数是getch()函数。getch()函数表示当用户在键盘上输入一个字符后,该字符立即被计算机接受,可以通过输出函数显示出来,而无需等待“回车”命令。&
输出字符putchar()
putchar函数是对单个字符进行输出的函数。它的功能:将指定表达式的值所对应的字符输出到标准设备(终端),每次只能输出一个字符。 &&&&&&格式:putchar(输出项) putchar()必须带输出项,输出项可以是字符型常量或变量,putchar函数功能与printf函数中的%c相当。例2:putchar函数的应用#include"stdio.h"main(){&&&&&&char o=‘O’,k=’K’; &&&&&&putchar(o); &&&&&&putchar(k); &&&&&&putchar(‘\n’);&&&&&&putchar(‘*’)}执行结果为:&&&&&& OK&&&&&&*使用putchar函数时,应注意以下几点: 1)输出的数据只能是单个字符,不能是字符串。’abc’或“abc”都是错误的。 2)被输出的字符常量必须用单引号括起来,如:’\n’、’*’。不能用双引号,导致错误。 3)当输出项是表达式的时候,可以写成a+等形式,不能写成a\n等形式。 另外,与putchar函数的功能和使用方法一样,putch函数也可以输出一个字符。
scanf函数的调用格式
scanf函数原型包含在标准输入输出头文件“stdio.h”中。调用格式: &&&&&&格式:scanf("格式控制字符串",输入项地址列表); scanf函数有两项参数,用“”引起来的格式控制字符串和需要接收数据的内存地址。格式控制字符串:规定数据输入的格式,由转换说明符和普通字符组成,转换说明符和百分号(%)一起使用,用来说明输入数据的数据类型(格式字符)。输入项地址列表:需要接收数据的变量地址,这些输入项与格式控制字符串在类型和数量上要对应,当有多个输入项时,各个地址名之间以逗号“,”分隔。输入格式和变量类型要保持一致。在C语言中,一个变量的地址可以通过地址运算符&得到。例如:定义int a,b;则a,b的地址为&a,&b。(见指针一章)scanf()函数中的输入项是变量地址,输入数据将被放入变量地址所指示的内存单元中,所以在变量前要加地址运算符“&”。
忘记变量前加地址操作符“&”是初学时容易犯的一个错误。现阶段只要记住scanf语句中的每个变量名前面都要有&,例外的情况在以后讨论。
——摘自高克宁 雒兴刚主编《高级语言程序设计》
scanf函数的格式说明
格式说明字符串规定了输入项中的变量将以何种类型的数据格式(由转换说明符给出)被输入,格式控制字符串的一般形式: &&&&&&% [修饰符] 转换说明符 其中修饰符为任选项。 1)格式转换说明符:用于指定相应输入项内容的输入格式,常用格式见下表1。
表1 scanf函数转换说明符
输入一个十进制整数
输入一个八进制整数
输入一个十六进制整数
输入一个有符号或无符号的十进制、八进制、十六进制整数
输入一个无符号十进制整数
f 、e或E、 g或G
输入一个小数形式或指数形式的浮点数
输入一个字符
输入一个字符串
例如:&&&&&&&&&&&&scanf(“%d”,&x); 它有两个参数“%d”和&x,第一个参数是格式控制字符串,由%后接一个类型转换说明符构成,指出用户应该输入的数据类型,转换说明符%d说明输入的数据应该是一个整数。第二个参数是变量x的地址,&与变量名连用是将变量x的内存地址告诉scanf函数,计算机然后就会将输入的数据存储在这个地址单元中。 计算机在执行scanf语句时,等待用户输入变量x的值,用户通过键入一个整数并按下回车键响应请求,计算机把用户的输入值赋给变量x,操作完成后,对x的引用就会使用这个值。scanf函数(及后面学习的printf函数)提高了用户与计算机之间的交互性。 在有多个输入项时,如果格式控制字符串中没有普通字符或转义字符作为读入数据之间的分隔符,则一般采用空格符、&Tab&符或回车键作为读入数据的分隔符,当C语言的编译系统空格符、&Tab&符或回车键以及非法字符时,会自动认为数据输入结束。计算机等待所有的数据输入结束后的最后一次&回车键&,将读入的数据分别付给对应的变量所指定的内存单元。如果数据的输入少于格式控制字符串中指定的转换说明符的个数,则计算机将一直等待数据的输入,直到所有数据全部被键入为止。 例如:&&&&&&int x,y; &&&&&&scanf(“%d%d”,&x,&y); 读入数据的方式可以是:&&&&&&1&空格&2&回车&或者&&&&&&1&回车&&&&&&&2&回车&或者&&&&& 1 &Tab&2&回车&采用“%d%d”形式的格式字时,不能使用其它的数据读入方式。例如:1,2&回车&,会使得只有1被送入x单元,而y单元不能够得到数据2。 但是,在输入多个带有字符型数据时,若以空格符作为分隔符,可能产生非预期的结果。此时,空格将被作为有效字符处理。 例如:&&&&&&int a; &&&&&&char ch; &&&&&&scanf(“%d%c”,&a,&ch); 如果数据读入方式为:123&空格&a&回车&,本意是期望变量a的值为数值32,变量ch的值为字符a,但实际上用于分隔数据的空格被作为有效字符数据读入并赋予给字符变量ch。为了避免这种情况,可以在格式控制字符串中加入空格作为分隔符。将上面例句改为:scanf(“%d %c”,&a,&ch);此处的%d后的空格,就可以跳过字符‘a’前所有的空格,从而保证非空格数据的正确录入。
2)修饰符 scanf函数的修饰符有:数据读入宽度(域宽)、*和长度。修饰符和意义见下表2。
表2 修饰符以及意义
指定输入数据的宽度
跳过相应数据不作处理
读入长整型、双精度型或短整型数据
①域宽 可以用一个十进制数指定输入数据的数据宽度,系统自动按域宽截取输入数据。 例如:&&&&&&int a; &&&&&&scanf(“%3d”,&a);表示按宽度3输入一个整数给变量a。如果读入数据为:123456&回车&,则变量a实际接收的值为123。 例如:&&&&&&int a,b,c; &&&&&&scanf(&#d%4d”,&a,&b,&c);如果读入数据为:&回车&,则变量a、b 、c 的值分别是12、345和6789。可以实现数据的自动截取。 ②字符* *表示按指定格式读入数据但不赋予相应的变量,作用是跳过相应的读入数据。 例如:&&&&&&int a,b,c; &&&&&&scanf(“%d%*d%d”,&a,&b,&c);执行该语句,若输入为1? 2? 3&回车&,结果为a=1,b=3,c未赋值,2被跳过。 例1:一个实际问题——处理一个日期数据。 假设日期读入的格式为: 12-2-/2003,该数据格式中的年、月、日三个数据需要保存,但是连接年、月、日数据的连接符需要被废弃。 当用户以12-02-2003形式键入日期数据时,该数据中的每一个数值(年、月、日)需要被读入对应的变量year、month、date内存单元中,为了去掉不需要的将年、月、日数据分开的连接符,直接方法是将这些字符包含在scanf的格式控制串中。 例如将语句写成:scanf(“%d─%d─%d’,&date,&month,&year);这条语句可以去掉以12-2-2003形式读入数据中的连字符,但是当用户输入如下格式的日期数据::12/2/:2003时,该语句语句不仅不能去掉不需要的字符(/或:),还会造成数据错误(只能正确得到date数据)。如果在输入格式字符串中使用scanf函数提供的*,将语句写成: scanf(“%d%*c%d%*c%d’,&date,&month,&year);就能够从输入数据中读取有效数据并废弃任何%*c所指定的数据(不将其赋给某个变量)。 程序清单如下: #include&stdio.h&main( ){ &&&&&&int month, day,&&&&&&printf("Enter a date in the form d-m-y:");&&&&&&scanf("%d%*c%d %*c%d",&date,&month,,&year);&&&&&&printf("date=%d month=%d year=%d\n",date ,month,year);}运行结果: &&&&&&Enter a date in the from d-m-y:12/3/2003&&&&&&day=12,month=3,year=2003
③l和h用于说明输入的数据时长整型(l)或短整型(h)。l和h可以和转换说明符d、o、x一起使用,形式为%ld、%lo、%lx、%hd、%ho、%hx,此外l还可以与f或e一起(%lf或%le)表示输入double型数据。 例如:&&&&&&&&&&&&&&&&&&scanf(“%10ld%hd”,&a,&b);表示变量a的数据按宽度为10的长整型读入,而变量b的数据按短整型读入。 3)普通字符(非格式字符) 格式控制字符串中除了格式字与修饰符外,还可以包含普通字符,这些普通字符包括:可打印字符、空格和转义字符。 ①可打印字符:对scanf函数,如果格式控制字符串中的说明符之间包含有其他字符,那么在输入数据时,必须在相应位置读入这些字符。 例如 :&&&&&&int a,b; &&&&&&scanf(“%d,%d”,&a,&b); 若数据输入:1&空格&2;则只有变量a的数据是正确的,变量b则会发生错误。这是因为格式控制字符串中存在可打印字符“,”,所以在读入数据时,必须以“,”作为输入数据的分隔符。正确地读入数据方式应为:1,2&回车&又如:scanf(“a=%d,b=%f,c=%c”,&a,&b,&c);当输入为:1,2,a时,虽然采用了“,”分隔数据,但也会产生错误,因为在格式控制字符串中还有其他的可打印字符(如:“a=”,“b=”,“c=”等)。也就是说,这些字符作为输入数据的分隔符,在scanf函数读入数据时自动去掉。因此正确地数据读入方式应为:a=1,b=2.1,c=a&回车&②空格 格式控制字符串中的空格可以分隔数据,在多个数据输入过程中,如果没有普通字符做数据的分隔符,则在数值数据输入时,可以用空格作为读入数据的分隔符,但在字符数据输入时,空格则不能作为数据之间的分隔符,它将被作为有效数据处理。 ③转义字符 在以%c格式的数据读入中,转义字符被作为有效字符处理。而在格式控制字符串中的转义字符具有输入转义字符所代表的控制代码或特殊字符的功能。 请分析下面程序代码: main(){&&&&&&int a,b;&&&&&&scanf("%d%d\n",&a,&b);&&&&&&printf("a=%d,b=%d\n",a,b);}如果输入1 2,会发生什么现象?应该怎样读入数据,才能得到执行结果?
尽量不要在scanf()函数的格式控制字符串中出现普通字符,特别是转义字符,它会增加读入数据的难度并可能造成不可预料的错误。
printf函数的调用格式
printf函数是一个标准库函数,能够以精确的格式输出程序运算的结果。printf函数的调用格式为: &&&&&&printf(“格式控制字符串”,输出项列表); printf函数有两项参数:用“”引起来的格式控制字符串和向标准设备输出的数据。每次调用printf函数时都要包含描述输出格式的 “格式控制字符串”。 格式字符串是由格式字符(包括:转换说明符、标志、域宽、精度)和普通字符组成,转换说明符和百分号(%)一起使用,用来说明输出数据的数据类型、标志、长度和精度。 输出项列表可以是常量、变量和表达式,也可以没有输出项,这些输出项必须与格式控制字符串在类型和数量上完全对应,否则,结果将不可预测。当有多个输出项时,各个输出项之间用逗号‘,’分隔。
在开始使用printf函数时最常犯的错误是忘记用双引号将格式控制字符串括起来。
——摘自高克宁 雒兴刚主编《高级语言程序设计》
&printf函数的最简单的使用
当没有输出项时,函数的参数只有“格式字符串”。函数完成的功能就是将“”中的字符串输出(显示在屏幕上)。 例1: 输出字符串hello Cprogramming! main() {&&&&&&printf(“hello Cprogramming!”); }可以在显示器屏幕上看到输出结果为:hello Cprogramming! printf函数永远不会自动换行,如果想将hello Cprogram!分行输出,输出形式如下: &&&&&&hello&&&&&&Cprogram!则需要引入转移字符\n,或者多次调用printf函数分段输出。程序如下:
main() {&&&&&&printf(“hello\n Cprogram!”); }或:main() {&&&&&&printf(“hello\n”); &&&&&&printf(“Cprogram!”); }
其中:“\n”是一个转移字符,是控制字符。它的作用是使计算机执行printf函数时,指示从下一行的右边开始的换新一行输出。所以显示器上出现了两行字符。如果在字符串中忘记了“\n”,那么输出的结果就没有换行(尽管可以多次调用printf函数)。例如下面的程序: main() {&&&&&&printf(“hello”); &&&&&&printf(“Cprogram!”); }输出结果仍为:hello Cprogram!转义字符的含义参见下表。
换新行起始符
回车(到本行起始)
横向制表符
纵向制表符
空字符(NULL)
1到3为八进制数所代表的字符
1到2位十六进制树所代表的字符
转义字符只能是用小写字母,每个转移字符被看成是一个字符常量。如:但是:用单引号‘’括起来的一个汉字如‘好’则不是字符常量;同样用双引号“”括起来的单个字符如“a” 也不是字符常量,它是字符串常量。
因为双引号“”、单引号‘’、反斜杠\等在C语言中的特殊作用,如果要在字符串重新打印这些字符,则不能直接使用这些字符,而要使用转义字符“\””、“\’”、“\\”等。 例如:输出“hello Cprogram!”,程序应改为: main() {&&&&&&printf(“\”hello Cprogram!\””); }
可以在printf()函数中适当的运用转义字符,以增加输出效果。但是要注意每个转义字符的不同含义,不要弄混。
——摘自高克宁 雒兴刚主编《高级语言程序设计》
格式化输出
在使用printf函数时,当系统遇到输出的转换说明符后,会自动用后面对应的输出项的值代替它的位置,然后输出。格式控制字符串中的转换字符应与输出列表中的待输出项之间应一一对应,这些转换字符控制对应的输出项以该格式输出。数据类型必须与格式符相匹配。 格式控制字符串的一般形式: &&&&&& % [修饰符] 转换说明符 其中修饰符为可选项,包括标志修饰符、宽度修饰符、精度修饰符、长度修饰符,用于确定输出数据的宽度、精度、对齐方式等,用于产生更加规范、整齐、美观的数据输出形式,当没有修饰符时,以上各项按系统缺省值设定显示。 1)转换说明符 转换说明符规定了对应输出项的输出格式,即将输出的数据转换为指定的格式输出。该项不能省略。常用的转换说明符及其含义见表1。
表1 转换说明符及其含义
转换说明符
按字符型输出
按十进制整数输出
按无符号十进制整数输出
按浮点型小数输出
按指数形式(科学计数法)输出
按八进制整数输出(不输出前缀o)
按十六进制整数输出(不输出前缀ox)
按字符串输出
按e和f格式中输出宽度较短的一种形式输出
转换说明符要与%一起使用,不能省略%。上表中的字符只有放在%的后面才作为输出的转换说明。 例如:&&&&&&int max; &&&&&&printf(“%d”,max); 表示变量max的值以十进制整数形式输出。 又如:&&&&&&int d=15; &&&&&&printf(“d=%d”,d); 在该格式控制字符串中,第1个d不是输出格式字而是一个普通字符,需要按原字符形式输出,第3个d是一个变量名,是输出项,只有放在%后的第2个d才是转换说明符, 说明变量d的值(15)以十进制整数形式输出。输出格式是:d=15。
printf()函数中的格式字中,除格式说明符E、G、X外,其它格式说明符必须小写。
例1:输出格式控制符的使用。 main( ){ &&&&&&int a1=+400,a2=-400;&&&&&&float b=3.1415926,e=98;&&&&&&float g=3.140000;&&&&&&char c='a';&&&&&&double d=3.8;&&&&&&printf("a1=%d\n",a1);&&&&&&printf("a1=%o\n",a1);&&&&&&printf("a1=%x\n",a1);&&&&&&printf("a1=%u\n",a1);&&&&&&printf("a2=%d\n",a2);&&&&&&printf("a2=%u\n",a2);&&&&&&printf("b=%f\n",b);&&&&&&printf("e=%e\n",e);&&&&&&printf("g=%g\n",g);&&&&&&printf("d=%f\n",d);&&&&&&printf("c=%c\n",c);&&&&&&printf("s=%s\n", "Cprogram");}执行程序,输出结果为:&&&&&&a1=400&&&&&&a1=620&&&&&&a1=190&&&&&&a1=400&&&&&&a2=-400&&&&&&a2=65136&&&&&&b=3.141593&&&&&&e=3.&&&&&&g=3.14&&&&&&d=3.141593&&&&&&c=a&&&&&&s=Cprogram从输出结果可以看出:只有减号(-)才会被打印出来,加号(+)是不打印的。?使用%u格式控制符打印正整数时,该数不发生变化,但是打印负整数时,该负整数将被转换为无符号整数并打印出来。?缺省情况下,使用%f、%e、%E打印出来的值带有6个小数位,如果小数位数不够6位,则在最后添0补位。?单精度数一般有7位有效数位。使用%e和%E打印的带有指数的值,在指数前打印出字母e或E,同时小数点左侧的数字仅打印一位(科学计数法)。双精度数可以用%f格式输出,它的有效位一般为16位,6位小数位。 %g不打印输出数据的小数部分尾部的0。 一个转换说明符是以%开始,以表3-2中的字符结束。其中可以插入修饰符。 2)长度修饰符 常用的长度修饰符有两种:l(长)表示按长整型量输出,h(短)表示按短整型量输出。可以和输出转换说明符d、f、u等连用。其用法和含义见表2。
表2 长度修饰符的意义
用于长整型数据的输出
用于短整型数据的输出
用于双精度型数据的输出
例2:长度修饰符的使用。 main(){&&&&&&long int a=1234567;&&&&&&int b=12345;&&&&&&double d=456789;&&&&&&printf("a=%ld\n",a);&&&&&&printf("b=%hd\n",b);&&&&&&printf("d=%lf\n",d);}执行程序,结果如下:&&&&&&a=1234567&&&&&&b=12345&&&&&&d=457例3:读入数据与输出数据类型的匹配。 main( ){ &&&&&&&&&&&&printf(“enter a data:\n”);&&&&&&scanf("%d",&a);&&&&&&printf("%d\n",a);}
程序运行结果:&&&&&&enter a data:&&&&&&&&&&&&-由于输入数据的类型为整型,读入的数据本身已超出基本整型范围,使计算结果发生错误,同时,输出函数的输出格式字为长整型,造成输出结果与输入数据不相符。因此应将程序修改如下:main( ){&&&&&&&&&&&&clrscr();&&&&&&printf("enter a data:\n");&&&&&&scanf("%ld",&a);&&&&&&printf("%ld\n",a);}&&&&&&enter a data:&&&&&&l&&&&&&
输入长整型数据时,应在数据的后面加上字母‘l’或‘L’。
3)宽度修饰符和精度修饰符 宽度修饰符用来指定printf()函数输出数据的占位宽度,用一个十进制整数表示输出数据的位数,插在百分号%与转换说明符之间,其作用是控制打印数据的宽度,也称为“域宽”。也可以在prinf函数中指定输出数据的精度。以一个小数点开始,后紧跟着一个十进制整数表示精度,插在百分号%与转换说明符之间。对于不同数据类型,精度的含义也不相同:在使用%d时,精度表示最少要打印的数字的个数。在使用%f、%e、%E时,精度是小数点后面显示的数字个数。在使用%s时,精度表示输出的字符串中字符的个数。
scanf不允许指定精度输入。
宽度和精度也可以同时使用,其使用形式是:域宽.精度。 常用的宽度修饰符与精度修饰符说明以及含义见表3。
表3 宽度修饰符与精度修饰符说明
修饰符及说明格式
以宽度m输出整型数,不足m位数时左侧补以空格。
以宽度m输出整型数,不足m位数时左侧补以0(零)。
以宽度m输出实型数,小数位数为n位。
以宽度m输出字符串,不足m位数时左侧补以空格。
以宽度m输出字符串左侧的n个字符,不足m位数时左侧补以空格。
例3:宽度修饰符和精度修饰符的使用。 main(){&&&&&&printf("%3d\n",1);&&&&&&printf("%3d\n",10);&&&&&&printf("%3d\n",100);&&&&&&printf("%3d\n",1000);&&&&&&printf("%0.3d\n",1);&&&&&&printf("%0.3d\n",10) ;&&&&&&printf("%0.3d\n",100);&&&&&&printf("%0.3d\n",1000);&&&&&&printf("%.3d\n",1);&&&&&&printf("%.3d\n",10);&&&&&&printf("%.3d\n",100);&&&&&&printf("%.3d\n",1000);&&&&&&printf("%7.2f\n",123.4567);&&&&&&printf("%5.2f\n",123.4567);&&&&&&printf("%2.7f\n",123.4567);&&&&&&printf("%5s\n","Cprogram");&&&&&&printf("%7.3s\n","Cprogram");&&&&&&printf("%2.6s\n","Cprogram");}执行程序,结果如下:&&&&&&1&&&&&&10&&&&&&100&&&&&&1000&&&&&&001&&&&&&010&&&&&&100&&&&&&1000&&&&&&001&&&&&&010&&&&&&100&&&&&&1000&&&&&&123.46&&&&&&123.46&&&&&&123.4567000&&&&&&Cprogram&&&&&&Cpr&&&&&&Cprogr分析程序的结果,可以看出:如果被打印的实际数据的宽度小于指定的宽度,则缺省下在宽度内为右对齐。左补空格或补0。直到总的数据个数满足宽度的要求。当指定的输出数据宽度小于数据的实际宽度时,则按实际数据的位数输出打印(宽度自动增加);对于整数而言,按该数的实际宽度输出;对于浮点数,按实际位数输出,但如果制定了浮点数的精度,则相应的小数位按精度的位数四舍五入;对于字符串,按实际串长度输出。通常情况下,精度用于描述浮点数的小数位数,但是,当采用精度描述整数或字符串时,如果被打印的整数数据包含的数字个数小于指定的精度,就在被打印数据的前面加0,直到总的数字个数等于该精度为止。而对于被打印的字符串,则精度确定该字符串左侧的字符个数,这些字符输出在指定域宽的右侧。不足域宽位数时左侧补以空格。在实际程序应用中,还有一种更为灵活的宽度和精度的控制方法,用整型常量或整型变量的值作为输出数据的域宽和精度。方法是以“*”取代域宽修饰符和精度修饰符放在%的后面,以计算出来的整数表达式的值作为宽度和精度。例如:&&&&&&float a=123.45;&&&&&&printf(“%*.*f”,6,1,a);此处6为输出宽度,1为输出精度,输出结果为: 123.5,右对齐。
没有为要打印的数据提供足够大的宽度,使得其他被打印的数据发生位置偏移,从而产生令人费解的输出格式。
4)标志修饰符 在printf 函数中,可以使用标志修饰符控制输出格式。常见的标志修饰符见表4。
表4 标志修饰符及其作用
标志修饰符
“左对齐”方式:输出数据左对齐,右侧补空格。缺省时输出数据则为右对齐,左补格。
输出数据为正时,在数据之前显示一个+号,为负时,在数据之前显示一个-号。
输出数据为八进制时加前缀0,为十六进制时前缀0x。
输出数据为正值时,在数据之前打印空格,为负时,数据之前显示一个-号。
例4:标志修饰符的使用。main(){&&&&&&printf("%10d\n",123);&&&&&&printf("%-10d\n",123);&&&&&&printf("%10.2f\n",123.45678);&&&&&&printf("%-10.2f\n",123.45678);&&&&&&printf("%10s\n","Cprogram");&&&&&&printf("%-10s\n","Cprogram") ;&&&&&&printf("\n");&&&&&&printf("%+5d\n",12345);&&&&&&printf("%+5d\n",-12345);&&&&&&printf("% 5d\n",12345);&&&&&&printf("% 5d\n",-12345);&&&&&&printf("\n");&&&&&&printf("%#o\n",100);&&&&&&printf("%o\n",100);&&&&&&printf("%#x\n",100);&&&&&&printf("%x\n",100);}执行程序,结果如下:&&&&&&123&&&&&&&&&&&&&&&&&&&123&&&&&&123.46&&&&&&123.46&&&&&&Cprogram&&&&&&&&&Cprogram
&&&&&&+12345&&&&&&-12345&&&&&&12345&&&&&&-12345
&&&&&&0144&&&&&&144&&&&&&0x64&&&&&&64
数据输出时,注意输出格式基对齐方式的统一,否则造成输出数据难以读懂。例如:&&&&&&int x=123,y=456;&&&&&&printf(“%3d%-3d”,x,y);其结果是:123456
5)普通字符 格式控制字符串中可以包含大量的可打印字符和转义字符,可打印字符主要是一些说明字符,这些字符将按原书写样式显示在屏幕上,如果有汉字系统支持,也可以输出汉字。转义字符是不可打印字符,用以控制产生特殊的输出效果。 例如:&&&&&&int a=123,b=12345;&&&&&&printf("a=%d,",a); &&&&&&printf("b=%d\n",b);其输出结果为:a=123,b=12345在第一个printf函数的格式控制字符串中,’a’、’=’和’,’都是普通字符,可以打印出来。第二个printf函数的格式控制字符串中的’b’和’=’也是可打印字符,但\n时是转义字符,不能够打印出来,表示要换行输出。将该程序改动一下,其输出形式也将发生改变。&&&&&&int a=123,b=12345;&&&&&&printf("a=%d\n",a); &&&&&&printf("b=%d\n",b);输出形式为:&&&&&&a=123&&&&&&b=12345在第一个printf函数的格式控制字符串中,a和=是普通字符,打印出来。’\n’虽然没有打印出来,但是它指示第二个printf函数换到下一行左侧输出。
——摘自高克宁 雒兴刚主编《高级语言程序设计》
TA的最新馆藏[转]&[转]&[转]&
喜欢该文的人也喜欢}

我要回帖

更多关于 c语言输出指针的值 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信