host: (Mac OS)
host-only: 网络名vnic1,可以使用ifconfig查看 10.37.129.2
bridge: 网络名vnic0,可以使用ifconfig查看 10.211.55.2
guest: (CentOS)
eth0
shell下修改:vi /etc/sysconfig/network-scripts/ifcfg-eth0
修改方法很简单
比如
# Advanced Micro Devices [AMD] 79c970 [PCnet32 LANCE]
DEVICE=eth0
BOOTPROTO=none
BROADCAST=192.168.1.255
HWADDR=00:0C:29:31:54:29
IPADDR=192.168.1.105
NETMASK=255.255.255.0
NETWORK=192.168.1.0
ONBOOT=yes
GATEWAY=192.168.1.1
TYPE=Ethernet
----------------------------------
默认情况下是动态IP,如何给guest设置静态IP?
Make sure that in Guest OS the netmask is 255.255.255.0 and gateway is 10.211.55.1
If this won't help and you are running Windows, post here the output of the "ipconfig /all" command.
Tuesday, November 29, 2011
Sunday, November 27, 2011
Linux下修改登陆模式---启动时进入命令行模式
1、进入root权限模式
su -
2、进入etc/目录下修改inittab文件的内容
vi inittab ------ 表示进入文件查看
i ------ 进入编辑,按下 'i' 后表示可以输入删除内容
ESC ------- 退出编辑模式
:wq ------- 保存并退出
修改/etc/inittab中的"id:5:initdefault:"
"5"为"3",restart即自动进入文本模式
su -
2、进入etc/目录下修改inittab文件的内容
vi inittab ------ 表示进入文件查看
i ------ 进入编辑,按下 'i' 后表示可以输入删除内容
ESC ------- 退出编辑模式
:wq ------- 保存并退出
修改/etc/inittab中的"id:5:initdefault:"
"5"为"3",restart即自动进入文本模式
Saturday, November 26, 2011
vmware workstation 7.1 安装linux是否能手动设置?
在建虚拟机的时候,选择:i will install the operating system later.
建好虚拟机再手动载光驱,iso.
建好虚拟机再手动载光驱,iso.
Tuesday, November 22, 2011
C语言输出格式
★ d格式符,用来输出十进制整数.
⑴%d,按整型数据的实际长度输出.
⑵%md,m为指定的输出字段的宽度,数据位数小于m,左边补空格,若大于m,按实际长度输出.
⑶%ld,输出长整型数据(long).
★ o格式符,以八进制输出整数(不带符号,他将符号位也作为八进制数的一部分了)
⑴%o,参考%d的解释.
⑵%lo,参考%ld的解释.
⑶%mo,参考%md的解释.
★ x,X格式符,以十六进制输出整数.
参考d格式符的3种解释.
★ u格式符,用来将unsigned型数据,既无符号数,以十进制形式输出.
★ c格式符,输出一个字符.
★ s格式符,输出一个字符串.
⑴%s,如printf("%s","CHINA").
⑵%ms,输出的字符串占m列,字符串长度小于m,左边补空格,如果超出则全部输出.
⑶%-ms,串小于m,则在m列范围内字符串左靠,右补空格.
⑷%m.ns,输出占m列,但只取字符串左端n个字符.这n个字符输出在m列的右边,然后左边补空格.
⑸%-m.ns,和上面的放下,就是n个字符输出在m列的左侧,右边补空格.n>m,那么m自动取n的值,既保证n个字符正常输出.
printf("%3s,%7.2s,%.4s,%-5.3s\n","CHINA","CHINA","CHINA","CHINA");
★ f格式符,用来输出实数,以小数形式输出.
⑴%f,全部输出,而且输出6位小数.
⑵%m.nf,输出数据共占m列,n位小数,如果数据长度小于m那么左边补空格.
⑶%-m.nf,和上面的m.nf相反,为左靠齐,右补空格.
★ e,E格式符,以指数形式输出实数
⑴%e,不指定输出数据所占的宽度和数字部分的小数位数.
⑵%m.ne和%-m.ne,这里n指小数部分的位数.
★ g,G格式符,用来输出实数,它根据数值大小,自动选择f格式还是e格式,(选占宽最少的一种),且不输出无意义的0.这种格式用的不多.
格式输出小结:
(1)最常用的格式是%d,含义是以10进制形式打印一个整数,如果输出的整数是负数,则,输出的第一个字符就是‘-’号.
(2)%u格式与%d格式类似,只不过要求打印无符号10进制整数.
(3)%o格式请求输出8进制整数.
(4)%x和%X格式请求输出16进制整数.
%x格式中用小写字母a,b,c,d,e,f来表示10到15之间的数
%X格式中用大写字母A,B,C,D,E,F来表示10到15之间的数
共同点:8进制和16进制整数总是作为无符号数处理的.
(5)%s格式用于打印字符串,与之对应的参数应该是一个字符指针,待输出的字符始于该指针所指向的地址,直到出现一个空字符('\0')才终止.
(6)%c格式用于打印单个字符,例如:
printf("%c",c); 等价于 putchar(c);
(7)%g,%f和%e这三个格式用于打印浮点值。%g格式用于打印那些不需要按列对齐的浮点数特别有用.
其作用有二:
一,去掉该数尾多余的零(没有达到六位的数)
二,保留六位有效数字(多余六位的)
%e格式用于打印浮点数时,一律显示地使用指数形式:例如:输出圆周率时是:3.141593e+00
两者的区别:
%g格式打印出的数是总共6位有效数字
%e格式打印出小数点后的6位有效数字
%f禁止使用指数形式来表示浮点数。因此圆周率输出为:3.141593
(但注意它的精度要求:也是小数点后6位有效数字)
(8)%%格式用于打印一个%字符.
(9)%E和%G只是在输出时用大写字母(E)代替了小写字母(e).
另外需要注意的一些知识点:
***************************************
对齐规则:
(1)当指定宽度大于要输出位数时,数右对齐,左端补空格
(2)当前缀'-'号时,想要数左对齐,右端补空格
(3)大大的前提:只有当“指定宽度”存在时,前缀'-'才有意义
经验:一般来说,左端对齐的形式看上去要美观整齐一点.
***************************************
输出正负号的技巧:
例如:printf("%+d %+d %+d\n",-5,0,5);
(1)只要在中间加个“+”号就行。作用是输出符号位(即,数的正负号)
(2)如果不希望正数的前面出现‘+’号,可用下面的方法.
***************************************
只要在中间加个" "号(即:空格)就行。(记住)
例如:作用:如果一个数是非负数,就在它的前面插入一个空格。
int i;
for(i=-3;i<=3;i++)
printf("% d\n",i); //注意%和d之间有一个空格
输出结果如下:
-3
-2
-1
0
1
2
3
问题:如果‘+’和‘ ’同时出现在“中间”时,要以‘+’为准。
两个符号的共同点:用于对齐输出的数:(尤其对于小数来说)
两种格式:%+e和% e
⑴%d,按整型数据的实际长度输出.
⑵%md,m为指定的输出字段的宽度,数据位数小于m,左边补空格,若大于m,按实际长度输出.
⑶%ld,输出长整型数据(long).
★ o格式符,以八进制输出整数(不带符号,他将符号位也作为八进制数的一部分了)
⑴%o,参考%d的解释.
⑵%lo,参考%ld的解释.
⑶%mo,参考%md的解释.
★ x,X格式符,以十六进制输出整数.
参考d格式符的3种解释.
★ u格式符,用来将unsigned型数据,既无符号数,以十进制形式输出.
★ c格式符,输出一个字符.
★ s格式符,输出一个字符串.
⑴%s,如printf("%s","CHINA").
⑵%ms,输出的字符串占m列,字符串长度小于m,左边补空格,如果超出则全部输出.
⑶%-ms,串小于m,则在m列范围内字符串左靠,右补空格.
⑷%m.ns,输出占m列,但只取字符串左端n个字符.这n个字符输出在m列的右边,然后左边补空格.
⑸%-m.ns,和上面的放下,就是n个字符输出在m列的左侧,右边补空格.n>m,那么m自动取n的值,既保证n个字符正常输出.
printf("%3s,%7.2s,%.4s,%-5.3s\n","CHINA","CHINA","CHINA","CHINA");
★ f格式符,用来输出实数,以小数形式输出.
⑴%f,全部输出,而且输出6位小数.
⑵%m.nf,输出数据共占m列,n位小数,如果数据长度小于m那么左边补空格.
⑶%-m.nf,和上面的m.nf相反,为左靠齐,右补空格.
★ e,E格式符,以指数形式输出实数
⑴%e,不指定输出数据所占的宽度和数字部分的小数位数.
⑵%m.ne和%-m.ne,这里n指小数部分的位数.
★ g,G格式符,用来输出实数,它根据数值大小,自动选择f格式还是e格式,(选占宽最少的一种),且不输出无意义的0.这种格式用的不多.
格式输出小结:
(1)最常用的格式是%d,含义是以10进制形式打印一个整数,如果输出的整数是负数,则,输出的第一个字符就是‘-’号.
(2)%u格式与%d格式类似,只不过要求打印无符号10进制整数.
(3)%o格式请求输出8进制整数.
(4)%x和%X格式请求输出16进制整数.
%x格式中用小写字母a,b,c,d,e,f来表示10到15之间的数
%X格式中用大写字母A,B,C,D,E,F来表示10到15之间的数
共同点:8进制和16进制整数总是作为无符号数处理的.
(5)%s格式用于打印字符串,与之对应的参数应该是一个字符指针,待输出的字符始于该指针所指向的地址,直到出现一个空字符('\0')才终止.
(6)%c格式用于打印单个字符,例如:
printf("%c",c); 等价于 putchar(c);
(7)%g,%f和%e这三个格式用于打印浮点值。%g格式用于打印那些不需要按列对齐的浮点数特别有用.
其作用有二:
一,去掉该数尾多余的零(没有达到六位的数)
二,保留六位有效数字(多余六位的)
%e格式用于打印浮点数时,一律显示地使用指数形式:例如:输出圆周率时是:3.141593e+00
两者的区别:
%g格式打印出的数是总共6位有效数字
%e格式打印出小数点后的6位有效数字
%f禁止使用指数形式来表示浮点数。因此圆周率输出为:3.141593
(但注意它的精度要求:也是小数点后6位有效数字)
(8)%%格式用于打印一个%字符.
(9)%E和%G只是在输出时用大写字母(E)代替了小写字母(e).
另外需要注意的一些知识点:
***************************************
对齐规则:
(1)当指定宽度大于要输出位数时,数右对齐,左端补空格
(2)当前缀'-'号时,想要数左对齐,右端补空格
(3)大大的前提:只有当“指定宽度”存在时,前缀'-'才有意义
经验:一般来说,左端对齐的形式看上去要美观整齐一点.
***************************************
输出正负号的技巧:
例如:printf("%+d %+d %+d\n",-5,0,5);
(1)只要在中间加个“+”号就行。作用是输出符号位(即,数的正负号)
(2)如果不希望正数的前面出现‘+’号,可用下面的方法.
***************************************
只要在中间加个" "号(即:空格)就行。(记住)
例如:作用:如果一个数是非负数,就在它的前面插入一个空格。
int i;
for(i=-3;i<=3;i++)
printf("% d\n",i); //注意%和d之间有一个空格
输出结果如下:
-3
-2
-1
0
1
2
3
问题:如果‘+’和‘ ’同时出现在“中间”时,要以‘+’为准。
两个符号的共同点:用于对齐输出的数:(尤其对于小数来说)
两种格式:%+e和% e
十大C++经典教程
1.《C++ Primer中文版》(第4版)
【原书名】 C++ Primer (4th Edition)
【原出版社】 Addison Wesley/Pearson
【作者】 (美)Stanley B.Lippman,Josée LaJoie,Barbara E.Moo
【译者】 李师贤
【丛书名】 图灵计算机科学丛书
【出版社】人民邮电出版社
本书是久负盛名的C++经典教程,其内容是C++大师Stanley B. Lippman丰富的实践经验和C++标准委员会原负责人Josée Lajoie对C++标准深入理解的完美结合,已经帮助全球无数程序员学会了C++.本版对前一版进行了彻底的修订,内容经过了重新组织,更加入了C++先驱Barbara E. Moo在C++教学方面的真知灼见。既显著改善了可读性,又充分体现了C++语言的最新进展和当前的业界最佳实践。书中不但新增大量教学辅助内容,用于强调重要的知识点,提醒常见的错误,推荐优秀的编程实践,给出使用提示,还包含大量来自实战的示例和习题。对C++基本概念和技术全面而且权威的阐述,对现代C++编程风格的强调,使本书成为C++初学者的最佳指南;对于中高级程序员,本书也是不可或缺的参考书。本书的前言阐述了 第4版和前一版的不同之处。
难度:★★☆
质量:★★★★★
广度:★★★★★
深度:★★★★
性价:★★★☆
2.《C++ Primer Plus》(第四版)中文版
【原书名】 C++ Primer Plus,Fourth Edition
【原出版社】 Sams
【作者】 (美)Stephen Prata
【译者】 孙建春 韦强
【丛书名】 Primer Plus 系列
【出版社】 人民邮电出版社
本书针对的是C++初学者,书中从C语言基础知识开始介绍,然后在此基础上详细阐述C++新增的特性,因此不要求读者有C语言方面的背景知识。本书可作为大中院校教授C++课程的教材,也可供初学者自学C++时使用。覆盖面较全,章节安排比较合理,由浅入深,也很容易,故因此失去了一些深度。价格比较便宜,但翻译质量略有不足。现在,第五版也出版了,不过还没有读,看章节都差不多。
难度:☆
质量:★★★☆
广度:★★★★
深度:★★★
性价:★★★☆
3.《Essential C++》(影印版)
【原书名】 Essential C++
【原出版社】Pearson Education
【作者】 (美)Stanley B.Lippman
【丛书名】 深入C++系列
【出版社】 中国电力出版社
lippman的一部面向初学者的作品。在他写了那么后一本primer之后,为何还要写这么薄这么浅的书呢?其实primer对于初学者来说太笨重了,而这本书却是从不同的方面——C++的本质和组织结构对语言进行阐释,可以帮助初学者对这门语言有一个大致的了解,但知识范围不很全面,不适合系统学习,读者需要一定的编程知识。
难度:★☆
质量:★★★★
广度:★★★☆
深度:★★★
性价:★★☆
4.《Effective C++》
【原书名】 Effective C++, Third Edition
【原出版社】 Addison Wesley/Pearson
【作者】 (美)Scott Meyers
【出版社】 电子工业出版社
《More Effective C++》
【原书名】 More Effective C++: 35 New Ways to Improve Your Programs and Designs
【原出版社】 Addison Wesley/Pearson
【作者】 (美)Scott Meyers
【丛书名】 C++设计新思维系列丛书
【出版社】 机械工业出版社
C++真牛人大手笔,之以条款的形式回答了程序员在使用C++时经常提出的“因该注意些什么?”,“因该避免什么?”,“因该怎样去解决?”,“为什么?”等问题。C++程序员想要让自己的水平上更高的档次,此二书必看。价格稍贵,有一定难度,不适合初学者。
难度:★★★☆
质量:★★★★★
广度:★★★
深度:★★★★★
性价:★★
5.《C++编程思想》
【原书名】 Thinking in C++
【原出版社】 McGraw Hill
【作者】 Bruce Eckel
【译者】 刘宗田 等
【丛书名】 计算机科学丛书
【出版社】 机械工业出版社
除了讲述语言之外,有一定的工程性,从设计者的角度来描述C++怎样应用在实际的项目中。语言描述的全面性欠佳,但还是有一定精度的,尤其是在一些小技巧方面。本书还引入了大量的战例,通过一个个的真实项目来引导你使用C++的思想去思考问题。翻译很差,有一定难度。
难度:★★☆
质量:★★★
广度:★★★☆
深度:★★★★
性价:★★★
6.《C++大学教程》(第二版)
【原书名】 The Complete C++ Training Course,Second Edition
【作者】 (美)Harvey M.Deitel Paul James Deitel
【译者】 邱仲潘 等
【丛书名】 国外计算机科学教材系列
【出版社】 电子工业出版社
正如其名,真正的大学教程,非常适合初学者学习,内容由浅入深,对C++各项特性的描述都很到位,章节的安排很有条理性,但深度略显不足,翻译质量不能称之为很好,有一定的疏漏,但对于厚度来讲,价格还算比较便宜。
难度:★
质量:★★★☆
广度:★★★★★
深度:★★★★
性价:★★★★☆
7.《C++语言的设计和演化》
【原书名】 The Design and Evolution of C++
【原出版社】 Addison-Wesley
【作者】 (美)Bjarne Stroustrup
【译者】 裘宗燕
【丛书名】 计算机科学丛书
【出版社】 机械工业出版社
对于热爱C++的朋友来说,确实好书一本,可以当做小说来读,可以放在厕所或床头上以供消遣。本书对语言本身描述很少,并有一定难度。读者需要对C++有一定了解,不适合初学者阅读。本书也有英文版,如果不喜欢翻译的朋友可以看看。
难度:★★★
质量:★★★
广度:★★☆
深度:★★★★
性价:★★★
8.《C++程序设计语言》
【原书名】 The C++ Programming Language, Special Edition
【原出版社】 Addison Wesley
【作者】 (美)Bjarne Stroustrup
【译者】 裘宗燕
【丛书名】 计算机科学丛书
【出版社】 机械工业出版社
C++之父所作,被称之为“C++圣经”。不仅对语言,而且对语言周边的一些如发展史、语义哲学都有比较详细的描述。对语言的描述较为全面,同时包含一部分和程序库相关联的知识,并有一定深度,适合有一定语言基础的初学者,翻译质量不错,价格适中。
难度:★☆
质量:★★★★☆
广度:★★★★☆
深度:★★★★
性价:★★★☆
9.《深度探索C++对象模型》(影印版)
【原书名】 Inside the C++ Object Model
【原出版社】 Pearson Education
【作者】 (美)Stanley B.Lippman
【丛书名】 深入C++系列
【出版社】 中国电力出版社
第一代C++编译器开发主管所写。如果你想成为真正的C++高手,看这本书,他为你讲述了编译器在处理各种语法时在“后台”所做的事。对C++有较深入了解的读者会在读后有恍然大悟之感。候杰翻译,质量相当不错,但内容太深,只适合对C++有较深了解的读者,价格偏贵。
难度:★★★★☆
质量:★★★★★
广度:★★★
深度:★★★★★
性价:★★
10.《C++程序设计教程》(钱能-清华版)
【作者】 钱能 董灵平 张敏霞
【丛书名】 C++程序设计系列教材
【出版社】 清华大学出版社
国人所著,国人水平实在有限,深度和广度欠佳,放在这十大里实在是因为再挑不出好书了。可圈可点之处有讲解较为清析、简单,符合中国学生思路,价格便宜。
难度:☆
质量:★★★
广度:★★★☆
深度:★★★
性价:★★★★★
【原书名】 C++ Primer (4th Edition)
【原出版社】 Addison Wesley/Pearson
【作者】 (美)Stanley B.Lippman,Josée LaJoie,Barbara E.Moo
【译者】 李师贤
【丛书名】 图灵计算机科学丛书
【出版社】人民邮电出版社
本书是久负盛名的C++经典教程,其内容是C++大师Stanley B. Lippman丰富的实践经验和C++标准委员会原负责人Josée Lajoie对C++标准深入理解的完美结合,已经帮助全球无数程序员学会了C++.本版对前一版进行了彻底的修订,内容经过了重新组织,更加入了C++先驱Barbara E. Moo在C++教学方面的真知灼见。既显著改善了可读性,又充分体现了C++语言的最新进展和当前的业界最佳实践。书中不但新增大量教学辅助内容,用于强调重要的知识点,提醒常见的错误,推荐优秀的编程实践,给出使用提示,还包含大量来自实战的示例和习题。对C++基本概念和技术全面而且权威的阐述,对现代C++编程风格的强调,使本书成为C++初学者的最佳指南;对于中高级程序员,本书也是不可或缺的参考书。本书的前言阐述了 第4版和前一版的不同之处。
难度:★★☆
质量:★★★★★
广度:★★★★★
深度:★★★★
性价:★★★☆
2.《C++ Primer Plus》(第四版)中文版
【原书名】 C++ Primer Plus,Fourth Edition
【原出版社】 Sams
【作者】 (美)Stephen Prata
【译者】 孙建春 韦强
【丛书名】 Primer Plus 系列
【出版社】 人民邮电出版社
本书针对的是C++初学者,书中从C语言基础知识开始介绍,然后在此基础上详细阐述C++新增的特性,因此不要求读者有C语言方面的背景知识。本书可作为大中院校教授C++课程的教材,也可供初学者自学C++时使用。覆盖面较全,章节安排比较合理,由浅入深,也很容易,故因此失去了一些深度。价格比较便宜,但翻译质量略有不足。现在,第五版也出版了,不过还没有读,看章节都差不多。
难度:☆
质量:★★★☆
广度:★★★★
深度:★★★
性价:★★★☆
3.《Essential C++》(影印版)
【原书名】 Essential C++
【原出版社】Pearson Education
【作者】 (美)Stanley B.Lippman
【丛书名】 深入C++系列
【出版社】 中国电力出版社
lippman的一部面向初学者的作品。在他写了那么后一本primer之后,为何还要写这么薄这么浅的书呢?其实primer对于初学者来说太笨重了,而这本书却是从不同的方面——C++的本质和组织结构对语言进行阐释,可以帮助初学者对这门语言有一个大致的了解,但知识范围不很全面,不适合系统学习,读者需要一定的编程知识。
难度:★☆
质量:★★★★
广度:★★★☆
深度:★★★
性价:★★☆
4.《Effective C++》
【原书名】 Effective C++, Third Edition
【原出版社】 Addison Wesley/Pearson
【作者】 (美)Scott Meyers
【出版社】 电子工业出版社
《More Effective C++》
【原书名】 More Effective C++: 35 New Ways to Improve Your Programs and Designs
【原出版社】 Addison Wesley/Pearson
【作者】 (美)Scott Meyers
【丛书名】 C++设计新思维系列丛书
【出版社】 机械工业出版社
C++真牛人大手笔,之以条款的形式回答了程序员在使用C++时经常提出的“因该注意些什么?”,“因该避免什么?”,“因该怎样去解决?”,“为什么?”等问题。C++程序员想要让自己的水平上更高的档次,此二书必看。价格稍贵,有一定难度,不适合初学者。
难度:★★★☆
质量:★★★★★
广度:★★★
深度:★★★★★
性价:★★
5.《C++编程思想》
【原书名】 Thinking in C++
【原出版社】 McGraw Hill
【作者】 Bruce Eckel
【译者】 刘宗田 等
【丛书名】 计算机科学丛书
【出版社】 机械工业出版社
除了讲述语言之外,有一定的工程性,从设计者的角度来描述C++怎样应用在实际的项目中。语言描述的全面性欠佳,但还是有一定精度的,尤其是在一些小技巧方面。本书还引入了大量的战例,通过一个个的真实项目来引导你使用C++的思想去思考问题。翻译很差,有一定难度。
难度:★★☆
质量:★★★
广度:★★★☆
深度:★★★★
性价:★★★
6.《C++大学教程》(第二版)
【原书名】 The Complete C++ Training Course,Second Edition
【作者】 (美)Harvey M.Deitel Paul James Deitel
【译者】 邱仲潘 等
【丛书名】 国外计算机科学教材系列
【出版社】 电子工业出版社
正如其名,真正的大学教程,非常适合初学者学习,内容由浅入深,对C++各项特性的描述都很到位,章节的安排很有条理性,但深度略显不足,翻译质量不能称之为很好,有一定的疏漏,但对于厚度来讲,价格还算比较便宜。
难度:★
质量:★★★☆
广度:★★★★★
深度:★★★★
性价:★★★★☆
7.《C++语言的设计和演化》
【原书名】 The Design and Evolution of C++
【原出版社】 Addison-Wesley
【作者】 (美)Bjarne Stroustrup
【译者】 裘宗燕
【丛书名】 计算机科学丛书
【出版社】 机械工业出版社
对于热爱C++的朋友来说,确实好书一本,可以当做小说来读,可以放在厕所或床头上以供消遣。本书对语言本身描述很少,并有一定难度。读者需要对C++有一定了解,不适合初学者阅读。本书也有英文版,如果不喜欢翻译的朋友可以看看。
难度:★★★
质量:★★★
广度:★★☆
深度:★★★★
性价:★★★
8.《C++程序设计语言》
【原书名】 The C++ Programming Language, Special Edition
【原出版社】 Addison Wesley
【作者】 (美)Bjarne Stroustrup
【译者】 裘宗燕
【丛书名】 计算机科学丛书
【出版社】 机械工业出版社
C++之父所作,被称之为“C++圣经”。不仅对语言,而且对语言周边的一些如发展史、语义哲学都有比较详细的描述。对语言的描述较为全面,同时包含一部分和程序库相关联的知识,并有一定深度,适合有一定语言基础的初学者,翻译质量不错,价格适中。
难度:★☆
质量:★★★★☆
广度:★★★★☆
深度:★★★★
性价:★★★☆
9.《深度探索C++对象模型》(影印版)
【原书名】 Inside the C++ Object Model
【原出版社】 Pearson Education
【作者】 (美)Stanley B.Lippman
【丛书名】 深入C++系列
【出版社】 中国电力出版社
第一代C++编译器开发主管所写。如果你想成为真正的C++高手,看这本书,他为你讲述了编译器在处理各种语法时在“后台”所做的事。对C++有较深入了解的读者会在读后有恍然大悟之感。候杰翻译,质量相当不错,但内容太深,只适合对C++有较深了解的读者,价格偏贵。
难度:★★★★☆
质量:★★★★★
广度:★★★
深度:★★★★★
性价:★★
10.《C++程序设计教程》(钱能-清华版)
【作者】 钱能 董灵平 张敏霞
【丛书名】 C++程序设计系列教材
【出版社】 清华大学出版社
国人所著,国人水平实在有限,深度和广度欠佳,放在这十大里实在是因为再挑不出好书了。可圈可点之处有讲解较为清析、简单,符合中国学生思路,价格便宜。
难度:☆
质量:★★★
广度:★★★☆
深度:★★★
性价:★★★★★
Monday, November 21, 2011
VC中TRACE
TRACE宏对于VC下程序调试来说是很有用的东西,有着类似printf的功能;该宏仅仅在程序的DEBUG版本中出现,当RELEASE的时候该宏就完全消失了,从而帮助你调试也在RELEASE的时候减少代码量。
使用非常简单,格式如下:
TRACE("DDDDDDDDDDD");
TRACE("wewe%d",333);
同样还存在TRACE0,TRACE1,TRACE2。。。分别对应0,1,2。。个参数
TRACE信息输出到VC IDE环境的输出窗口(该窗口是你编译项目出错提示的那个窗口),但仅限于你在VC中运行你的DEBUG版本的程序。
TRACE信息还可以使用DEBUGVIEW来捕获到。这种情况下,你不能在VC的IDE环境中运行你的程序,而将BUILD好的DEBUG版本的程序单独运行,这个时候可以在DEBUGVIEW的窗口看到DEBUGVIE格式的输出了。
VC中TRACE的用法有以下四种:
1:
TRACE ,就是不带动态参数输出字符串, 类似C的printf("输出字符串");
2:
TRACE 中的字符串可以带一个参数输出 , 类似C的printf("...%d",变量);
3:
TRACE 可以带两个参数输出,类似C的printf("...%d...%f",变量1,变量2);
4:
TRACE 可以带三个参数输出,类似C的printf("...%d,%d,%d",变量1,变量2,变量3);
TRACE 宏有点象我们以前在C语言中用的Printf函数,使程序在运行过程中输出一些调试信息,使我们能了解程序的一些状态。但有一点不同的是:
TRACE 宏只有在调试状态下才有所输出,而以前用的Printf 函数在任何情况下都有输出。和Printf 函数一样,TRACE函数可以接受多个参数如:
int x = 1;
int y = 16;
float z = 32.0;
TRACE( "This is a TRACE statement/n" );
TRACE( "The value of x is %d/n", x );
TRACE( "x = %d and y = %d/n", x, y );
TRACE( "x = %d and y = %x and z = %f/n", x, y, z );
要注意的是TRACE宏只对Debug 版本的工程产生作用,在Release 版本的工程中,TRACE宏将被忽略。
使用非常简单,格式如下:
TRACE("DDDDDDDDDDD");
TRACE("wewe%d",333);
同样还存在TRACE0,TRACE1,TRACE2。。。分别对应0,1,2。。个参数
TRACE信息输出到VC IDE环境的输出窗口(该窗口是你编译项目出错提示的那个窗口),但仅限于你在VC中运行你的DEBUG版本的程序。
TRACE信息还可以使用DEBUGVIEW来捕获到。这种情况下,你不能在VC的IDE环境中运行你的程序,而将BUILD好的DEBUG版本的程序单独运行,这个时候可以在DEBUGVIEW的窗口看到DEBUGVIE格式的输出了。
VC中TRACE的用法有以下四种:
1:
TRACE ,就是不带动态参数输出字符串, 类似C的printf("输出字符串");
2:
TRACE 中的字符串可以带一个参数输出 , 类似C的printf("...%d",变量);
3:
TRACE 可以带两个参数输出,类似C的printf("...%d...%f",变量1,变量2);
4:
TRACE 可以带三个参数输出,类似C的printf("...%d,%d,%d",变量1,变量2,变量3);
TRACE 宏有点象我们以前在C语言中用的Printf函数,使程序在运行过程中输出一些调试信息,使我们能了解程序的一些状态。但有一点不同的是:
TRACE 宏只有在调试状态下才有所输出,而以前用的Printf 函数在任何情况下都有输出。和Printf 函数一样,TRACE函数可以接受多个参数如:
int x = 1;
int y = 16;
float z = 32.0;
TRACE( "This is a TRACE statement/n" );
TRACE( "The value of x is %d/n", x );
TRACE( "x = %d and y = %d/n", x, y );
TRACE( "x = %d and y = %x and z = %f/n", x, y, z );
要注意的是TRACE宏只对Debug 版本的工程产生作用,在Release 版本的工程中,TRACE宏将被忽略。
C语言八进制和十六进制
八进制:012 040 093 -01151 -0157 04663 -067756 051013 (在C/C++中,八进制开头要加0,来说明这个整数是八进制数)
十六进制:0xa 0x20 0x4b -0x269 0x6f 0x9b3 -0x6fee 0x520b(在C/C++中,十六进制开头要加0x,来说明这个整数是十六进制数)
十六进制:0xa 0x20 0x4b -0x269 0x6f 0x9b3 -0x6fee 0x520b(在C/C++中,十六进制开头要加0x,来说明这个整数是十六进制数)
typedef struct 用法详解
第一篇:typedef struct与struct的区别
1. 基本解释
typedef为C语言的关键字,作用是为一种数据类型定义一个新名字。这里的数据类型包括内部数据类型(int,char等)和自定义的数据类型(struct等)。
在编程中使用typedef目的一般有两个,一个是给变量一个易记且意义明确的新名字,另一个是简化一些比较复杂的类型声明。
至于typedef有什么微妙之处,请你接着看下面对几个问题的具体阐述。
2. typedef & 结构的问题
当用下面的代码定义一个结构时,编译器报了一个错误,为什么呢?莫非C语言不允许在结构中包含指向它自己的指针吗?请你先猜想一下,然后看下文说明:
typedef struct tagNode
{
char *pItem;
pNode pNext;
} *pNode;
答案与分析:
1、typedef的最简单使用
typedef long byte_4;
给已知数据类型long起个新名字,叫byte_4。
2、 typedef与结构结合使用
typedef struct tagMyStruct
{
int iNum;
long lLength;
} MyStruct;
这语句实际上完成两个操作:
1) 定义一个新的结构类型
struct tagMyStruct
{
int iNum;
long lLength;
};
分析:tagMyStruct称为“tag”,即“标签”,实际上是一个临时名字,struct 关键字和tagMyStruct一起,构成了这个结构类型,不论是否有typedef,这个结构都存在。
我们可以用struct tagMyStruct varName来定义变量,但要注意,使用tagMyStruct varName来定义变量是不对的,因为struct 和tagMyStruct合在一起才能表示一个结构类型。
2) typedef为这个新的结构起了一个名字,叫MyStruct。
typedef struct tagMyStruct MyStruct;
因此,MyStruct实际上相当于struct tagMyStruct,我们可以使用MyStruct varName来定义变量。
答案与分析
C语言当然允许在结构中包含指向它自己的指针,我们可以在建立链表等数据结构的实现上看到无数这样的例子,上述代码的根本问题在于typedef的应用。
根据我们上面的阐述可以知道:新结构建立的过程中遇到了pNext域的声明,类型是pNode,要知道pNode表示的是类型的新名字,那么在类型本身还没有建立完成的时候,这个类型的新名字也还不存在,也就是说这个时候编译器根本不认识pNode。
解决这个问题的方法有多种:
1)、
typedef struct tagNode
{
char *pItem;
struct tagNode *pNext;
} *pNode;
2)、
typedef struct tagNode *pNode;
struct tagNode
{
char *pItem;
pNode pNext;
};
注意:在这个例子中,你用typedef给一个还未完全声明的类型起新名字。C语言编译器支持这种做法。
3)、规范做法:
typedef uint32 (* ADM_READDATA_PFUNC)( uint16*, uint32 );
这个以前没有看到过,个人认为是宇定义一个uint32的指针函数,uint16*, uint32 为函数里的两个参数; 应该相当于#define uint32 (* ADM_READDATA_PFUNC)( uint16*, uint32 );
struct在代码中常见两种形式:
struct A
{
//...
};
struct
{
//...
} A;
这其实是两个完全不同的用法:
前者叫做“结构体类型定义”,意思是:定义{}中的结构为一个名称是“A”的结构体。
这种用法在typedef中一般是:
typedef struct tagA //故意给一个不同的名字,作为结构体的实名
{
//...
} A; //结构体的别名。
后者是结构体变量定义,意思是:以{}中的结构,定义一个名称为"A"的变量。这里的结构体称为匿名结构体,是无法被直接引用的。
也可以通过typedef为匿名结构体创建一个别名,从而使得它可以被引用:
typedef struct
{
//...
} A; //定义匿名结构体的别名为A
第二篇:在C和C++中struct和typedef struct的区别
在C和C++有三种定义结构的方法。
typedef struct {
int data;
int text;
} S1;
//这种方法可以在c或者c++中定义一个S1结构
struct S2 {
int data;
int text;
};
// 这种定义方式只能在C++中使用,而如果用在C中,那么编译器会报错
struct {
int data;
int text;
} S3;
这种方法并没有定义一个结构,而是定义了一个s3的结构变量,编译器会为s3内存。
void main()
{
S1 mine1;// OK ,S1 是一个类型
S2 mine2;// OK,S2 是一个类型
S3 mine3;// OK,S3 不是一个类型
S1.data = 5;// ERRORS1 是一个类型
S2.data = 5;// ERRORS2 是一个类型
S3.data = 5;// OKS3是一个变量
}
另外,对与在结构中定义结构本身的变量也有几种写法
struct S6 {
S6* ptr;
};
// 这种写法只能在C++中使用
typedef struct {
S7* ptr;
} S7;
// 这是一种在C和C++中都是错误的定义
如果在C中,我们可以使用这样一个“曲线救国的方法“
typedef struct tagS8{
tagS8 * ptr;
} S8;
第三篇:struct和typedef struct
分三块来讲述:
1 首先:
在C中定义一个结构体类型要用typedef:
typedef struct Student
{
int a;
}Stu;
于是在声明变量的时候就可:Stu stu1;
如果没有typedef就必须用struct Student stu1;来声明
这里的Stu实际上就是struct Student的别名。
另外这里也可以不写Student(于是也不能struct Student stu1;了)
typedef struct
{
int a;
}Stu;
但在c++里很简单,直接
struct Student
{
int a;
};
于是就定义了结构体类型Student,声明变量时直接Student stu2;
===========================================
2其次:
在c++中如果用typedef的话,又会造成区别:
struct Student
{
int a;
}stu1;//stu1是一个变量
typedef struct Student2
{
int a;
}stu2;//stu2是一个结构体类型
使用时可以直接访问stu1.a
但是stu2则必须先 stu2 s2;
然后 s2.a=10;
===========================================
3 掌握上面两条就可以了,不过最后我们探讨个没多大关系的问题
如果在c程序中我们写:
typedef struct
{
int num;
int age;
}aaa,bbb,ccc;
这算什么呢?
我个人观察编译器(VC6)的理解,这相当于
typedef struct
{
int num;
int age;
}aaa;
typedef aaa bbb;
typedef aaa ccc;
也就是说aaa,bbb,ccc三者都是结构体类型。声明变量时用任何一个都可以,在c++中也是如此。但是你要注意的是这个在c++中如果写掉了typedef关键字,那么aaa,bbb,ccc将是截然不同的三个对象。
第四篇:C/C++中typedef struct和struct的用法
struct _x1 { ...}x1; 和 typedef struct _x2{ ...} x2; 有什么不同?
其实, 前者是定义了类_x1和_x1的对象实例x1, 后者是定义了类_x2和_x2的类别名x2 ,
所以它们在使用过程中是有取别的.请看实例1.
[知识点]
结构也是一种数据类型, 可以使用结构变量, 因此, 象其它 类型的变量一样, 在使用结构变量时要先对其定义。
定义结构变量的一般格式为:
struct 结构名
{
类型 变量名;
类型 变量名;
...
} 结构变量;
结构名是结构的标识符不是变量名。
另一种常用格式为:
typedef struct 结构名
{
类型 变量名;
类型 变量名;
...
} 结构别名;
另外注意: 在C中,struct不能包含函数。在C++中,对struct进行了扩展,可以包含函数。
======================================================================
实例1: struct.cpp
#include
using namespace std;
typedef struct _point{
int x;
int y;
}point; //定义类,给类一个别名
struct _hello{
int x,y;
} hello; //同时定义类和对象
int main()
{
point pt1;
pt1.x = 2;
pt1.y = 5;
cout<< "ptpt1.x=" << pt1.x << "pt.y=" <
//hello pt2;
//pt2.x = 8;
//pt2.y =10;
//cout<<"pt2pt2.x="<< pt2.x <<"pt2.y="<
//上面的hello pt2;这一行编译将不能通过. 为什么?
//因为hello是被定义了的对象实例了.
//正确做法如下: 用hello.x和hello.y
hello.x = 8;
hello.y = 10;
cout<< "hellohello.x=" << hello.x << "hello.y=" <
return 0;
}
第五篇:问答
Q:用struct和typedef struct 定义一个结构体有什么区别?为什么会有两种方式呢?
struct Student
{
int a;
} stu;
typedef struct Student2
{
int a;
}stu2;
A:
事实上,这个东西是从C语言中遗留过来的,typedef可以定义新的复合类型或给现有类型起一个别名,在C语言中,如果你使用
struct xxx
{
}; 的方法,使用时就必须用 struct xxx var 来声明变量,而使用
typedef struct
{
}的方法 就可以写为 xxx var;
不过在C++中已经没有这回事了,无论你用哪一种写法都可以使用第二种方式声明变量,这个应该算是C语言的糟粕。
1. 基本解释
typedef为C语言的关键字,作用是为一种数据类型定义一个新名字。这里的数据类型包括内部数据类型(int,char等)和自定义的数据类型(struct等)。
在编程中使用typedef目的一般有两个,一个是给变量一个易记且意义明确的新名字,另一个是简化一些比较复杂的类型声明。
至于typedef有什么微妙之处,请你接着看下面对几个问题的具体阐述。
2. typedef & 结构的问题
当用下面的代码定义一个结构时,编译器报了一个错误,为什么呢?莫非C语言不允许在结构中包含指向它自己的指针吗?请你先猜想一下,然后看下文说明:
typedef struct tagNode
{
char *pItem;
pNode pNext;
} *pNode;
答案与分析:
1、typedef的最简单使用
typedef long byte_4;
给已知数据类型long起个新名字,叫byte_4。
2、 typedef与结构结合使用
typedef struct tagMyStruct
{
int iNum;
long lLength;
} MyStruct;
这语句实际上完成两个操作:
1) 定义一个新的结构类型
struct tagMyStruct
{
int iNum;
long lLength;
};
分析:tagMyStruct称为“tag”,即“标签”,实际上是一个临时名字,struct 关键字和tagMyStruct一起,构成了这个结构类型,不论是否有typedef,这个结构都存在。
我们可以用struct tagMyStruct varName来定义变量,但要注意,使用tagMyStruct varName来定义变量是不对的,因为struct 和tagMyStruct合在一起才能表示一个结构类型。
2) typedef为这个新的结构起了一个名字,叫MyStruct。
typedef struct tagMyStruct MyStruct;
因此,MyStruct实际上相当于struct tagMyStruct,我们可以使用MyStruct varName来定义变量。
答案与分析
C语言当然允许在结构中包含指向它自己的指针,我们可以在建立链表等数据结构的实现上看到无数这样的例子,上述代码的根本问题在于typedef的应用。
根据我们上面的阐述可以知道:新结构建立的过程中遇到了pNext域的声明,类型是pNode,要知道pNode表示的是类型的新名字,那么在类型本身还没有建立完成的时候,这个类型的新名字也还不存在,也就是说这个时候编译器根本不认识pNode。
解决这个问题的方法有多种:
1)、
typedef struct tagNode
{
char *pItem;
struct tagNode *pNext;
} *pNode;
2)、
typedef struct tagNode *pNode;
struct tagNode
{
char *pItem;
pNode pNext;
};
注意:在这个例子中,你用typedef给一个还未完全声明的类型起新名字。C语言编译器支持这种做法。
3)、规范做法:
typedef uint32 (* ADM_READDATA_PFUNC)( uint16*, uint32 );
这个以前没有看到过,个人认为是宇定义一个uint32的指针函数,uint16*, uint32 为函数里的两个参数; 应该相当于#define uint32 (* ADM_READDATA_PFUNC)( uint16*, uint32 );
struct在代码中常见两种形式:
struct A
{
//...
};
struct
{
//...
} A;
这其实是两个完全不同的用法:
前者叫做“结构体类型定义”,意思是:定义{}中的结构为一个名称是“A”的结构体。
这种用法在typedef中一般是:
typedef struct tagA //故意给一个不同的名字,作为结构体的实名
{
//...
} A; //结构体的别名。
后者是结构体变量定义,意思是:以{}中的结构,定义一个名称为"A"的变量。这里的结构体称为匿名结构体,是无法被直接引用的。
也可以通过typedef为匿名结构体创建一个别名,从而使得它可以被引用:
typedef struct
{
//...
} A; //定义匿名结构体的别名为A
第二篇:在C和C++中struct和typedef struct的区别
在C和C++有三种定义结构的方法。
typedef struct {
int data;
int text;
} S1;
//这种方法可以在c或者c++中定义一个S1结构
struct S2 {
int data;
int text;
};
// 这种定义方式只能在C++中使用,而如果用在C中,那么编译器会报错
struct {
int data;
int text;
} S3;
这种方法并没有定义一个结构,而是定义了一个s3的结构变量,编译器会为s3内存。
void main()
{
S1 mine1;// OK ,S1 是一个类型
S2 mine2;// OK,S2 是一个类型
S3 mine3;// OK,S3 不是一个类型
S1.data = 5;// ERRORS1 是一个类型
S2.data = 5;// ERRORS2 是一个类型
S3.data = 5;// OKS3是一个变量
}
另外,对与在结构中定义结构本身的变量也有几种写法
struct S6 {
S6* ptr;
};
// 这种写法只能在C++中使用
typedef struct {
S7* ptr;
} S7;
// 这是一种在C和C++中都是错误的定义
如果在C中,我们可以使用这样一个“曲线救国的方法“
typedef struct tagS8{
tagS8 * ptr;
} S8;
第三篇:struct和typedef struct
分三块来讲述:
1 首先:
在C中定义一个结构体类型要用typedef:
typedef struct Student
{
int a;
}Stu;
于是在声明变量的时候就可:Stu stu1;
如果没有typedef就必须用struct Student stu1;来声明
这里的Stu实际上就是struct Student的别名。
另外这里也可以不写Student(于是也不能struct Student stu1;了)
typedef struct
{
int a;
}Stu;
但在c++里很简单,直接
struct Student
{
int a;
};
于是就定义了结构体类型Student,声明变量时直接Student stu2;
===========================================
2其次:
在c++中如果用typedef的话,又会造成区别:
struct Student
{
int a;
}stu1;//stu1是一个变量
typedef struct Student2
{
int a;
}stu2;//stu2是一个结构体类型
使用时可以直接访问stu1.a
但是stu2则必须先 stu2 s2;
然后 s2.a=10;
===========================================
3 掌握上面两条就可以了,不过最后我们探讨个没多大关系的问题
如果在c程序中我们写:
typedef struct
{
int num;
int age;
}aaa,bbb,ccc;
这算什么呢?
我个人观察编译器(VC6)的理解,这相当于
typedef struct
{
int num;
int age;
}aaa;
typedef aaa bbb;
typedef aaa ccc;
也就是说aaa,bbb,ccc三者都是结构体类型。声明变量时用任何一个都可以,在c++中也是如此。但是你要注意的是这个在c++中如果写掉了typedef关键字,那么aaa,bbb,ccc将是截然不同的三个对象。
第四篇:C/C++中typedef struct和struct的用法
struct _x1 { ...}x1; 和 typedef struct _x2{ ...} x2; 有什么不同?
其实, 前者是定义了类_x1和_x1的对象实例x1, 后者是定义了类_x2和_x2的类别名x2 ,
所以它们在使用过程中是有取别的.请看实例1.
[知识点]
结构也是一种数据类型, 可以使用结构变量, 因此, 象其它 类型的变量一样, 在使用结构变量时要先对其定义。
定义结构变量的一般格式为:
struct 结构名
{
类型 变量名;
类型 变量名;
...
} 结构变量;
结构名是结构的标识符不是变量名。
另一种常用格式为:
typedef struct 结构名
{
类型 变量名;
类型 变量名;
...
} 结构别名;
另外注意: 在C中,struct不能包含函数。在C++中,对struct进行了扩展,可以包含函数。
======================================================================
实例1: struct.cpp
#include
using namespace std;
typedef struct _point{
int x;
int y;
}point; //定义类,给类一个别名
struct _hello{
int x,y;
} hello; //同时定义类和对象
int main()
{
point pt1;
pt1.x = 2;
pt1.y = 5;
cout<< "ptpt1.x=" << pt1.x << "pt.y=" <
//hello pt2;
//pt2.x = 8;
//pt2.y =10;
//cout<<"pt2pt2.x="<< pt2.x <<"pt2.y="<
//上面的hello pt2;这一行编译将不能通过. 为什么?
//因为hello是被定义了的对象实例了.
//正确做法如下: 用hello.x和hello.y
hello.x = 8;
hello.y = 10;
cout<< "hellohello.x=" << hello.x << "hello.y=" <
return 0;
}
第五篇:问答
Q:用struct和typedef struct 定义一个结构体有什么区别?为什么会有两种方式呢?
struct Student
{
int a;
} stu;
typedef struct Student2
{
int a;
}stu2;
A:
事实上,这个东西是从C语言中遗留过来的,typedef可以定义新的复合类型或给现有类型起一个别名,在C语言中,如果你使用
struct xxx
{
}; 的方法,使用时就必须用 struct xxx var 来声明变量,而使用
typedef struct
{
}的方法 就可以写为 xxx var;
不过在C++中已经没有这回事了,无论你用哪一种写法都可以使用第二种方式声明变量,这个应该算是C语言的糟粕。
C语言 单引号和双引号的区别
1、含义不同。
用单引号引起的一个字符实际上代表一个整数,整数值对应于该字符在编译器采用的字符集中的序列值。而一般我们的编译器采用的都是ASCII字符集。因此's'的含义其实和十进制数115的含义是一致的。
而用双引号引起的字符串,代表的是一个指向无名数组起始字符的指针。
2、大小不同。
用单引号引起的一个字符大小就是一个字节。
而用双引号引起的字符串大小是字符的总大小+1,因为用双引号引起的字符串会在字符串末尾添加一个二进制为0的字符'\0'。
用单引号引起的一个字符实际上代表一个整数,整数值对应于该字符在编译器采用的字符集中的序列值。而一般我们的编译器采用的都是ASCII字符集。因此's'的含义其实和十进制数115的含义是一致的。
而用双引号引起的字符串,代表的是一个指向无名数组起始字符的指针。
2、大小不同。
用单引号引起的一个字符大小就是一个字节。
而用双引号引起的字符串大小是字符的总大小+1,因为用双引号引起的字符串会在字符串末尾添加一个二进制为0的字符'\0'。
C语言程序结构和语法规则
一、C语言程序的基本结构
下面通过几个简单的示例,介绍C语言程序的基本构成和书写格式,使读者对C语言程序有一个基本的了解。在此基础上,再进一步了解C语言程序的语法和书写规则。
【例1.1】 求三个数的平均值的C语言程序。
/*功能:求三个数的平均值*/
main() /* main()称为主函数*/
{
float a,b,c,ave; /* 定义a,b,c,ave为实型数据*/
a=7;
b=9;
c=12;
ave=(a+b+c)/3; /*计算平均值*/
printf("ave=%f\n",ave); /* 在屏幕上输出ave的值 */
}
程序运行结果:
ave=9.333333
【例1.2】 输出两个数中的较大值的C语言程序。
/*功能:输出两个数中的较大值 */
main() /*主函数*/
{
int num1,num2,max; /*定义num1、num2、max为整型变量*/
scanf("%d,%d",&num1,&num2); /*由键盘输入num1、num2的值*/
printf("max=%d\n",max(num1,num2)); /*在屏幕上输出调用max的函数值*/
}
/*用户设计的函数max()*/
int max(int x,int y) /* x和y分别取num1和num2传递的值*/
{
if(x>y) return x; /* 如果x>y,将x的值返回给max */
else return y; /* 如果x>y不成立,将y的值返回给max */
}
程序运行情况:
5,8↙(“↙”表示按回车键,以下相同)
max=8
在以上两个示例中,【例1.1】所示的C语言程序仅由一个main()函数构成,它相当于其他高级语言中的主程序;【例1.2】所示的C语言程序由一个main()和一个其他函数max()(用户自己设计的函数)构成,函数max()相当于其他高级语言中的子程序。由此可见,一个完整的C语言程序结构有以下两种表现形式:
(1)仅由一个main()函数(又称主函数)构成,如图1-1(a)所示。
(2)由一个且只能有一个main()函数和若干个其他函数结合而成,如图1-1(b)所示。其中,自定义函数由用户自己设计。
图1-1 C语言程序结构示意图
结合以上示例,可以看出C语言程序结构有以下基本特点:
(1)C语言程序是由函数(如:main函数和max函数)组成的,每一个函数完成相对独立的功能,函数是C语言程序的基本模块单元。main是函数名,函数名后面的一对圆括号“()”是用来写函数的参数的。参数可以有,也可以没有(本程序没有参数),但圆括号不能省略。
(2)一个C语言程序总是从main()函数开始执行。主函数执行完毕,程序执行结束。
(3)C语言编译系统区分字母大小写。C语言把大小写字母视为两个不同的字符,并规定每条语句或数据说明均以分号(;)结束。分号是语句不可缺少的组成部分。
(4)主函数main()既可以放在max()函数之前,也可以放在max()函数之后。习惯上,将主函数main()放在最前面。
(5)C语言程序中所调用的函数,既可以是由系统提供的库函数,也可以是由设计人员自己根据需要而设计的函数。例如,在【例1.2】中,printf()函数是C语言编译系统库函数中的一个函数,它的作用是在屏幕上按指定格式输出指定的内容;max()函数是由用户自己设计的函数,它的作用是计算两个数中的较大值。
二、C语言程序的书写规则
(1)C源程序是由一个主函数和若干个其它函数组成的。
(2)函数名后必须有小括号,函数体放在大括号内。
(3)C程序必须用小写字母书写。
(4)每句的末尾加分号。
(5)可以一行多句。
(6)可以一句多行。
(7)可以在程序的任何位置加注释。
一个完整的C语言程序,是由一个main()函数(又称主函数)和若干个其它函数结合而成的,或仅由一个main()函数构成。
[例1.3] 仅由main()函数构成的C语言程序。
main()
{
printf(“This is a C program.\n”);
}
程序运行结果:
This is a C program.
[例1.4] 由main()函数和1个其它函数max()构成的C语言程序。
int max(int x, int y)
{
return( x>y ? x : y );
}
main()
{
int num1,num2;
printf(“Input the first integer number: ”);
scanf(“%d”, &num1);
printf(“Input the second integer number: ”);
scanf(“%d”, &num2);
printf(“max=%d\n”, max(num1, num2));
}
程序运行情况:
Input the first integer number:6←┘
Input the second integer number:9←┘
max=9
下面通过几个简单的示例,介绍C语言程序的基本构成和书写格式,使读者对C语言程序有一个基本的了解。在此基础上,再进一步了解C语言程序的语法和书写规则。
【例1.1】 求三个数的平均值的C语言程序。
/*功能:求三个数的平均值*/
main() /* main()称为主函数*/
{
float a,b,c,ave; /* 定义a,b,c,ave为实型数据*/
a=7;
b=9;
c=12;
ave=(a+b+c)/3; /*计算平均值*/
printf("ave=%f\n",ave); /* 在屏幕上输出ave的值 */
}
程序运行结果:
ave=9.333333
【例1.2】 输出两个数中的较大值的C语言程序。
/*功能:输出两个数中的较大值 */
main() /*主函数*/
{
int num1,num2,max; /*定义num1、num2、max为整型变量*/
scanf("%d,%d",&num1,&num2); /*由键盘输入num1、num2的值*/
printf("max=%d\n",max(num1,num2)); /*在屏幕上输出调用max的函数值*/
}
/*用户设计的函数max()*/
int max(int x,int y) /* x和y分别取num1和num2传递的值*/
{
if(x>y) return x; /* 如果x>y,将x的值返回给max */
else return y; /* 如果x>y不成立,将y的值返回给max */
}
程序运行情况:
5,8↙(“↙”表示按回车键,以下相同)
max=8
在以上两个示例中,【例1.1】所示的C语言程序仅由一个main()函数构成,它相当于其他高级语言中的主程序;【例1.2】所示的C语言程序由一个main()和一个其他函数max()(用户自己设计的函数)构成,函数max()相当于其他高级语言中的子程序。由此可见,一个完整的C语言程序结构有以下两种表现形式:
(1)仅由一个main()函数(又称主函数)构成,如图1-1(a)所示。
(2)由一个且只能有一个main()函数和若干个其他函数结合而成,如图1-1(b)所示。其中,自定义函数由用户自己设计。
图1-1 C语言程序结构示意图
结合以上示例,可以看出C语言程序结构有以下基本特点:
(1)C语言程序是由函数(如:main函数和max函数)组成的,每一个函数完成相对独立的功能,函数是C语言程序的基本模块单元。main是函数名,函数名后面的一对圆括号“()”是用来写函数的参数的。参数可以有,也可以没有(本程序没有参数),但圆括号不能省略。
(2)一个C语言程序总是从main()函数开始执行。主函数执行完毕,程序执行结束。
(3)C语言编译系统区分字母大小写。C语言把大小写字母视为两个不同的字符,并规定每条语句或数据说明均以分号(;)结束。分号是语句不可缺少的组成部分。
(4)主函数main()既可以放在max()函数之前,也可以放在max()函数之后。习惯上,将主函数main()放在最前面。
(5)C语言程序中所调用的函数,既可以是由系统提供的库函数,也可以是由设计人员自己根据需要而设计的函数。例如,在【例1.2】中,printf()函数是C语言编译系统库函数中的一个函数,它的作用是在屏幕上按指定格式输出指定的内容;max()函数是由用户自己设计的函数,它的作用是计算两个数中的较大值。
二、C语言程序的书写规则
(1)C源程序是由一个主函数和若干个其它函数组成的。
(2)函数名后必须有小括号,函数体放在大括号内。
(3)C程序必须用小写字母书写。
(4)每句的末尾加分号。
(5)可以一行多句。
(6)可以一句多行。
(7)可以在程序的任何位置加注释。
一个完整的C语言程序,是由一个main()函数(又称主函数)和若干个其它函数结合而成的,或仅由一个main()函数构成。
[例1.3] 仅由main()函数构成的C语言程序。
main()
{
printf(“This is a C program.\n”);
}
程序运行结果:
This is a C program.
[例1.4] 由main()函数和1个其它函数max()构成的C语言程序。
int max(int x, int y)
{
return( x>y ? x : y );
}
main()
{
int num1,num2;
printf(“Input the first integer number: ”);
scanf(“%d”, &num1);
printf(“Input the second integer number: ”);
scanf(“%d”, &num2);
printf(“max=%d\n”, max(num1, num2));
}
程序运行情况:
Input the first integer number:6←┘
Input the second integer number:9←┘
max=9
Sunday, November 20, 2011
C语言之指针、数组和函数
基本解释
1、指针的本质是一个与地址相关的复合类型,它的值是数据存放的位置(地址);数组的本质则是一系列的变量。
2、数组名对应着(而不是指向)一块内存,其地址与容量在生命期内保持不变,只有数组的内容可以改变。指针可以随时指向任意类型的内存块,它的特征是“可变”,所以我们常用指针来操作动态内存。
3、当数组作为函数的参数进行传递时,该数组自动退化为同类型的指针。
问题:指针与数组
听说char a[]与char *a是一致的,是不是这样呢?
答案与分析:
指针和数组存在着一些本质的区别。当然,在某种情况下,比如数组作为函数的参数进行传递时,由于该数组自动退化为同类型的指针,所以在函数内部,作为函数参数传递进来的指针与数组确实具有一定的一致性,但这只是一种比较特殊的情况而已,在本质上,两者是有区别的。请看以下的例子:
char a[] = "Hi, pig!";
char *p = "Hi, pig!";
上述两个变量的内存布局分别如下:
数组a需要在内存中占用8个字节的空间,这段内存区通过名字a来标志。指针p则需要4个字节的空间来存放地址,这4个字节用名字p来标志。其中存放的地址几乎可以指向任何地方,也可以哪里都不指,即空指针。目前这个p指向某地连续的8个字节,即字符串“Hi, pig!”。
另外,例如:对于a[2]和p[2],二者都返回字符‘i’,但是编译器产生的执行代码却不一样。对于a[2],执行代码是从a的位置开始,向后移 动2两个字节,然后取出其中的字符。对于p[2],执行代码是从p的位置取出一个地址,在其上加2,然后取出对应内存中的字符。
问题:数组指针
为什么在有些时候我们需要定义指向数组而不是指向数组元素的指针?如何定义?
答案与分析:
使用指针,目的是用来保存某个元素的地址,从而来利用指针独有的优点,那么在元素需要是数组的情况下,就理所当然要用到指向数组的指针,比如在高维需要动态生成情况下的多维数组。
定义例子如下: int (*pElement)[2]。
下面是一个例子:
int array[2][3] = {{1,2,3},{4,5,6}};
int (*pa)[3]; //定义一个指向数组的指针
pa = &array[0]; // '&'符号能够体现pa的含义,表示是指向数组的指针
printf ("%d", (*pa)[0]); //将打印array[0][0],即1
pa++; // 猜一猜,它指向谁?array[1]?对了!
printf ("%d", (*pa)[0]); // 将打印array[1][0],即4
上述这个例子充分说明了数组指针—一种指向整个数组的指针的定义和使用。
需要说明的是,按照我们在第四篇讨论过的,指针的步进是参照其所指对象的大小的,因此,pa++将整个向后移 动一个数组的尺寸,而不是仅仅向后移 动一个数组元素的尺寸。
问题:指针数组
有如下定义:
struct UT_TEST_STRUCT *pTo[2][MAX_NUM];
请分析这个定义的意义,并尝试说明这样的定义可能有哪些好处?
答案与分析:
前面我们谈了数组指针,现在又提到了指针数组,两者形式很相似,那么,如何区分两者的定义呢?分析如下:
数组指针是:指向数组的指针,比如 int (*pA)[5]。
指针数组是:指针构成的数组,比如int *pA[5]。
至于上述指针数组的好处,大致有如下两个很普遍的原因:
a)、各个指针内容可以按需要动态生成,避免了空间浪费。
b)、各个指针呈数组形式排列,索引起来非常方便。
在实际编程中,选择使用指针数组大多都是想要获得如上两个好处。
问题:指向指针的指针
在做一个文本处理程序的时候,有这样一个问题:什么样的数据结构适合于按行存储文本?
答案与分析:
首先,我们来分析文本的特点,文本的主要特征是具有很强的动态性,一行文本的字符个数或多或少不确定,整个文本所拥有的文本行数也是不确定的。这样的特征决定了用固定的二维数组存放文本行必然限制多多,缺乏灵活性。这种场合,使用指向指针的指针有很大的优越性。
现实中我们尝试用动态二维数组(本质就是指向指针的指针)来解决此问题:
图示是一个指针数组。所谓动态性指横向(对应每行文本的字符个数)和纵向(对应整个文本的行数)两个方向都可以变化。
就横向而言,因为指针的灵活性,它可以指向随意大小的字符数组,实现了横向动态性。
就竖向而言,可以动态生成及扩展需要的指针数组的大小。
下面的代码演示了这种动态数组的用途:
// 用于从文件中读取以 '/0'结尾的字符串的函数
extern char *getline(FILE *pFile);
FILE *pFile;
char **ppText = NULL; // 二维动态数组指针
char *pCurrText = NULL; // 指向当前输入字符串的指针
ULONG ulCurrLines = 0;
ULONG ulAllocedLines = 0;
while (p = getline(pFile))
{
if (ulCurrLines >= ulAllocedLines)
{
// * 当前竖向空间已经不够了,通过realloc对其进行扩展。
ulAllocedLines += 50; // 每次扩展50行。
ppText = realloc (ppText, ulAllocedLines * (char *));
if (NULL == ppText)
{
return; // 内存分配失败,返回
}
}
ppText[ulCurrLines++] = p; // 横向“扩展”,指向不定长字符串
}
问题:指针数组与数组指针与指向指针的指针
指针和数组分别有如下的特征:
指针:动态分配,初始空间小
数组:索引方便,初始空间大
下面使用高维数组来说明指针数组、数组指针、指向指针的指针各自的适合场合。
多维静态数组:各维均确定,适用于整体空间需求不大的场合,此结构可方便索引,例a[10][40]。
数组指针:低维确定,高维需要动态生成的场合,例a[x][40]。
指针数组:高维确定,低维需要动态生成的场合,例a[10][y]。
指向指针的指针:高、低维均需要动态生成的场合,例a[x][y]。
问题:数组名相关问题
假设有一个整数数组a,a和&a的区别是什么?
答案与分析:
a == &a == &a[0],数组名a不占用存储空间。需要引用数组(非字符串)首地址的地方,我一般使用&a[0],使用a容易和指针混淆,使用&a容易和非指针变量混淆。
区别在于二者的类型。对数组a的直接引用将产生一个指向数组第一个元素的指针,而&a的结果则产生一个指向全部数组的指针。例如:
int a[2] = {1, 2};
int *p = 0;
p = a; /* p指向a[0]所在的地方 */
x = *p; /* x = a[0] = 1*/
p = &a; /* 编译器会提示你错误,*/
/*显示整数指针与整数数组指针不一样 */
问题:函数指针与指针函数
请问:如下定义是什么意思:
int *pF1();
int (*pF2)();
答案与分析:
首先清楚它们的定义:
指针函数,返回一个指针的函数。
函数指针,指向一个函数的指针。
可知:
pF1是一个指针函数,它返回一个指向int型数据的指针。
pF2是一个函数指针,它指向一个参数为空的函数,这个函数返回一个整数。
1、指针的本质是一个与地址相关的复合类型,它的值是数据存放的位置(地址);数组的本质则是一系列的变量。
2、数组名对应着(而不是指向)一块内存,其地址与容量在生命期内保持不变,只有数组的内容可以改变。指针可以随时指向任意类型的内存块,它的特征是“可变”,所以我们常用指针来操作动态内存。
3、当数组作为函数的参数进行传递时,该数组自动退化为同类型的指针。
问题:指针与数组
听说char a[]与char *a是一致的,是不是这样呢?
答案与分析:
指针和数组存在着一些本质的区别。当然,在某种情况下,比如数组作为函数的参数进行传递时,由于该数组自动退化为同类型的指针,所以在函数内部,作为函数参数传递进来的指针与数组确实具有一定的一致性,但这只是一种比较特殊的情况而已,在本质上,两者是有区别的。请看以下的例子:
char a[] = "Hi, pig!";
char *p = "Hi, pig!";
上述两个变量的内存布局分别如下:
数组a需要在内存中占用8个字节的空间,这段内存区通过名字a来标志。指针p则需要4个字节的空间来存放地址,这4个字节用名字p来标志。其中存放的地址几乎可以指向任何地方,也可以哪里都不指,即空指针。目前这个p指向某地连续的8个字节,即字符串“Hi, pig!”。
另外,例如:对于a[2]和p[2],二者都返回字符‘i’,但是编译器产生的执行代码却不一样。对于a[2],执行代码是从a的位置开始,向后移 动2两个字节,然后取出其中的字符。对于p[2],执行代码是从p的位置取出一个地址,在其上加2,然后取出对应内存中的字符。
问题:数组指针
为什么在有些时候我们需要定义指向数组而不是指向数组元素的指针?如何定义?
答案与分析:
使用指针,目的是用来保存某个元素的地址,从而来利用指针独有的优点,那么在元素需要是数组的情况下,就理所当然要用到指向数组的指针,比如在高维需要动态生成情况下的多维数组。
定义例子如下: int (*pElement)[2]。
下面是一个例子:
int array[2][3] = {{1,2,3},{4,5,6}};
int (*pa)[3]; //定义一个指向数组的指针
pa = &array[0]; // '&'符号能够体现pa的含义,表示是指向数组的指针
printf ("%d", (*pa)[0]); //将打印array[0][0],即1
pa++; // 猜一猜,它指向谁?array[1]?对了!
printf ("%d", (*pa)[0]); // 将打印array[1][0],即4
上述这个例子充分说明了数组指针—一种指向整个数组的指针的定义和使用。
需要说明的是,按照我们在第四篇讨论过的,指针的步进是参照其所指对象的大小的,因此,pa++将整个向后移 动一个数组的尺寸,而不是仅仅向后移 动一个数组元素的尺寸。
问题:指针数组
有如下定义:
struct UT_TEST_STRUCT *pTo[2][MAX_NUM];
请分析这个定义的意义,并尝试说明这样的定义可能有哪些好处?
答案与分析:
前面我们谈了数组指针,现在又提到了指针数组,两者形式很相似,那么,如何区分两者的定义呢?分析如下:
数组指针是:指向数组的指针,比如 int (*pA)[5]。
指针数组是:指针构成的数组,比如int *pA[5]。
至于上述指针数组的好处,大致有如下两个很普遍的原因:
a)、各个指针内容可以按需要动态生成,避免了空间浪费。
b)、各个指针呈数组形式排列,索引起来非常方便。
在实际编程中,选择使用指针数组大多都是想要获得如上两个好处。
问题:指向指针的指针
在做一个文本处理程序的时候,有这样一个问题:什么样的数据结构适合于按行存储文本?
答案与分析:
首先,我们来分析文本的特点,文本的主要特征是具有很强的动态性,一行文本的字符个数或多或少不确定,整个文本所拥有的文本行数也是不确定的。这样的特征决定了用固定的二维数组存放文本行必然限制多多,缺乏灵活性。这种场合,使用指向指针的指针有很大的优越性。
现实中我们尝试用动态二维数组(本质就是指向指针的指针)来解决此问题:
图示是一个指针数组。所谓动态性指横向(对应每行文本的字符个数)和纵向(对应整个文本的行数)两个方向都可以变化。
就横向而言,因为指针的灵活性,它可以指向随意大小的字符数组,实现了横向动态性。
就竖向而言,可以动态生成及扩展需要的指针数组的大小。
下面的代码演示了这种动态数组的用途:
// 用于从文件中读取以 '/0'结尾的字符串的函数
extern char *getline(FILE *pFile);
FILE *pFile;
char **ppText = NULL; // 二维动态数组指针
char *pCurrText = NULL; // 指向当前输入字符串的指针
ULONG ulCurrLines = 0;
ULONG ulAllocedLines = 0;
while (p = getline(pFile))
{
if (ulCurrLines >= ulAllocedLines)
{
// * 当前竖向空间已经不够了,通过realloc对其进行扩展。
ulAllocedLines += 50; // 每次扩展50行。
ppText = realloc (ppText, ulAllocedLines * (char *));
if (NULL == ppText)
{
return; // 内存分配失败,返回
}
}
ppText[ulCurrLines++] = p; // 横向“扩展”,指向不定长字符串
}
问题:指针数组与数组指针与指向指针的指针
指针和数组分别有如下的特征:
指针:动态分配,初始空间小
数组:索引方便,初始空间大
下面使用高维数组来说明指针数组、数组指针、指向指针的指针各自的适合场合。
多维静态数组:各维均确定,适用于整体空间需求不大的场合,此结构可方便索引,例a[10][40]。
数组指针:低维确定,高维需要动态生成的场合,例a[x][40]。
指针数组:高维确定,低维需要动态生成的场合,例a[10][y]。
指向指针的指针:高、低维均需要动态生成的场合,例a[x][y]。
问题:数组名相关问题
假设有一个整数数组a,a和&a的区别是什么?
答案与分析:
a == &a == &a[0],数组名a不占用存储空间。需要引用数组(非字符串)首地址的地方,我一般使用&a[0],使用a容易和指针混淆,使用&a容易和非指针变量混淆。
区别在于二者的类型。对数组a的直接引用将产生一个指向数组第一个元素的指针,而&a的结果则产生一个指向全部数组的指针。例如:
int a[2] = {1, 2};
int *p = 0;
p = a; /* p指向a[0]所在的地方 */
x = *p; /* x = a[0] = 1*/
p = &a; /* 编译器会提示你错误,*/
/*显示整数指针与整数数组指针不一样 */
问题:函数指针与指针函数
请问:如下定义是什么意思:
int *pF1();
int (*pF2)();
答案与分析:
首先清楚它们的定义:
指针函数,返回一个指针的函数。
函数指针,指向一个函数的指针。
可知:
pF1是一个指针函数,它返回一个指向int型数据的指针。
pF2是一个函数指针,它指向一个参数为空的函数,这个函数返回一个整数。
C语言指针的运算
指针的运算实质是地址的运算。c语言有一套适用于指针、数组等地址运算的规则,正是这套规则赋予了C语言出色的处理能力。
对于指针指向变量,能进行基类型数据所能进行的全部运算。
1.引用运算
1)取地址运算(&)
取地址运算“&”,我们已非常熟悉。对指针变量进行取地址运算,可以得到指针变量本身的地址。
2)取内容运算(*)
取内容运算“*”,前称指针运算,用于获取地址数据对应存储单元的内容。取内容运算的优先级与取地址运算优先级相同,也为第2级,结合性亦为右结合。对指针变量,进行取内容运算可以得到指针变量所指向的数据。
取内容运算与取地址运算实质上是一对互逆运算。例如:
int a, p=&a;
*(&a)就是a,&(*p)就是p;p指向a,*p与a等价。
2.算术运算
指针变量可以进行有限的算术运算。
1)加减运算
指针变量“加上”或“减去”一个整数n,相当于指针变量加上或减去n个指针所指向数据的存储单位,即指针由当前指向位置向后或向前移动n个指针所指向数据的存储单位。
加减运算常用于数组的处理。对指向一般数据的指针,加减运算无实际意义。例如;
int a[10],*p=a,*x;
x=p+3;/*实际上是p加上3*2个字节赋给x,x指向数组的第三个分量*/
对于不同基类型的指针,指针变量“加上”或“减去”一个整数n所移动的字节数是不同的。例如:
float a[10],*p=a,*x;
p=p+3;/*实际上是p加上3*4个字节赋给x,x依然指向数组的第三个分量*/
2)自增自减运算
指针变量自增、自减运算具有上述运算的特点,但有前置后置、先用后用的考虑,务请小心。例如:
int a[10],*p=a,*x;
x=p++;/*x指向数组的第一个分量,p指向数组的第二个分量*/
x=++p;/*x、p均指向数组的第二个分量*/
*p++相当于*(p++)。*(p++)与(*p)++含义不同,前者表示地址自增,后者表示当前所指向的数据自增。
3)指针相减
指针相减得到两指针之间数据的个数,一般用于数组处理。
3.关系运算
两指针的关系运算表示两指针的先后位置关系,一般用于数组处理。除空指针外,不
能进行指针与一般数值的关系运算。
对于指针指向变量,能进行基类型数据所能进行的全部运算。
1.引用运算
1)取地址运算(&)
取地址运算“&”,我们已非常熟悉。对指针变量进行取地址运算,可以得到指针变量本身的地址。
2)取内容运算(*)
取内容运算“*”,前称指针运算,用于获取地址数据对应存储单元的内容。取内容运算的优先级与取地址运算优先级相同,也为第2级,结合性亦为右结合。对指针变量,进行取内容运算可以得到指针变量所指向的数据。
取内容运算与取地址运算实质上是一对互逆运算。例如:
int a, p=&a;
*(&a)就是a,&(*p)就是p;p指向a,*p与a等价。
2.算术运算
指针变量可以进行有限的算术运算。
1)加减运算
指针变量“加上”或“减去”一个整数n,相当于指针变量加上或减去n个指针所指向数据的存储单位,即指针由当前指向位置向后或向前移动n个指针所指向数据的存储单位。
加减运算常用于数组的处理。对指向一般数据的指针,加减运算无实际意义。例如;
int a[10],*p=a,*x;
x=p+3;/*实际上是p加上3*2个字节赋给x,x指向数组的第三个分量*/
对于不同基类型的指针,指针变量“加上”或“减去”一个整数n所移动的字节数是不同的。例如:
float a[10],*p=a,*x;
p=p+3;/*实际上是p加上3*4个字节赋给x,x依然指向数组的第三个分量*/
2)自增自减运算
指针变量自增、自减运算具有上述运算的特点,但有前置后置、先用后用的考虑,务请小心。例如:
int a[10],*p=a,*x;
x=p++;/*x指向数组的第一个分量,p指向数组的第二个分量*/
x=++p;/*x、p均指向数组的第二个分量*/
*p++相当于*(p++)。*(p++)与(*p)++含义不同,前者表示地址自增,后者表示当前所指向的数据自增。
3)指针相减
指针相减得到两指针之间数据的个数,一般用于数组处理。
3.关系运算
两指针的关系运算表示两指针的先后位置关系,一般用于数组处理。除空指针外,不
能进行指针与一般数值的关系运算。
C语言中strcmp
strcmp是比较两个字符串的大小,两个字符串相同时返回0,第一个字符串大于第二个字符串时返回一个正值,否则返回负值.
比较两个字符串的算法是:逐个比较两个串中对应的字符,字符大小按照ASCII码值确定,从左向右比较,如果遇到不同字符,所遇第一对不同字符的大小关系就确定了两个字符串的大小关系,如果未遇到不同字符而某个字符串首先结束,那么这个字符串是较小的,否则两个字符串相等。
比较两个字符串的算法是:逐个比较两个串中对应的字符,字符大小按照ASCII码值确定,从左向右比较,如果遇到不同字符,所遇第一对不同字符的大小关系就确定了两个字符串的大小关系,如果未遇到不同字符而某个字符串首先结束,那么这个字符串是较小的,否则两个字符串相等。
C语言main()参数详解
main()函数既可以是无参函数,也可以是有参的函数。对于有参的形式来说,就需要向其传递参数。但是其它任何函数均不能调用main()函数。当然也同样无法向main()函数传递,只能由程序之外传递而来。这个具体的问题怎样解决呢?
我们先看一下main()函数的带参的形式:
main(int argc,char *argv[])
{
.....
}
从函数参数的形式上看,包含一个整型和一个指针数组。当一个C的源程序经过编译、链接后,会生成扩展名为.EXE的可执行文件,这是可以在操作系统下直接运行的文件,换句话说,就是由系统来启动运行的。对main()函数既然不能由其它函数调用和传递参数,就只能由系统在启动运行时传递参数了;
在编译连接好得到一个可执行文件test.exe后,将在系统执行这个可执行文件时,将参数一起传入,./test.exe a b c d
a b c d 分别为四个参数,其关系为 :
argc = 5
argv[0]=./test.exe
argv[1]=a
argv[2]=b
argv[3]=c
argv[4]=d
前面介绍的main函数都是不带参数的。因此main 后的括号都是空括号。实际上,main函数可以带参数,这个参数可以认为是 main函数的形式参数。C语言规定main函数的参数只能有两个, 习惯上这两个参数写为argc和argv。因此,main函数的函数头可写为: main (argc,argv)C语言还规定argc(第一个形参)必须是整型变量,argv( 第二个形参)必须是指向字符串的指针数组。加上形参说明后,main函数的函数头应写为:
main (argc,argv)
int argv;
char *argv[];或写成:
main (int argc,char *argv[])
由于main函数不能被其它函数调用, 因此不可能在程序内部取得实际值。那么,在何处把实参值赋予main函数的形参呢? 实际上,main函数的参数值是从操作系统命令行上获得的。当我们要运行一个可执行文件时,在DOS提示符下键入文件名,再输入实际参数即可把这些实参传送到main的形参中去。
DOS提示符下命令行的一般形式为: C:\>可执行文件名 参数 参数……; 但是应该特别注意的是,main 的两个形参和命令行中的参数在
位置上不是一一对应的。因为,main的形参只有二个,而命令行中的参数个数原则上未加限制。argc参数表示了命令行中参数的个数(注意:文件名本身也算一个参数),argc的值是在输入命令行时由系统按实际参数的个数自动赋予的。例如有命令行为: C:\>E6 24 BASIC dbase FORTRAN由于文件名E6 24本身也算一个参数,所以共有4个参数,因此argc取得的值为4。argv参数是字符串指针数组,其各元素值为命令行中各字符串(参数均按字符串处理)的首地址。 指针数组的长度即为参数个数。数组元素初值由系统自动赋予。其表示如图6.8所示:
main(int argc,char *argv){
while(argc-->1)
printf("%s\n",*++argv);
}
本例是显示命令行中输入的参数如果上例的可执行文件名为e24.exe,存放在A驱动器的盘内。
因此输入的命令行为: C:\>a:e24 BASIC dBASE FORTRAN
则运行结果为:
BASIC
dBASE
FORTRAN
该行共有4个参数,执行main时,argc的初值即为4。argv的4个元素分为4个字符串的首地址。执行while语句,每循环一次 argv值减1,当argv等于1时停止循环,共循环三次, 因此共可输出三个参数。在printf函数中,由于打印项*++argv是先加1再打印, 故第一次打印的是argv[1]所指的字符串BASIC。第二、 三次循环分别打印后二个字符串。而参数e24是文件名,不必输出。
下例的命令行中有两个参数,第二个参数20即为输入的n值。在程序中*++argv的值为字符串“20”,然后用函数"atoi"把它换为整型作为while语句中的循环控制变量,输出20个偶数。
#include"stdlib.h"
main(int argc,char*argv[]){
int a=0,n;
n=atoi(*++argv);
while(n--) printf("%d ",a++*2);
}
本程序是从0开始输出n个偶数。指向指针的指针变量如果一个指针变量存放的又是另一个指针变量的地址, 则称这个指针变量为指向指针的指针变量。
我们先看一下main()函数的带参的形式:
main(int argc,char *argv[])
{
.....
}
从函数参数的形式上看,包含一个整型和一个指针数组。当一个C的源程序经过编译、链接后,会生成扩展名为.EXE的可执行文件,这是可以在操作系统下直接运行的文件,换句话说,就是由系统来启动运行的。对main()函数既然不能由其它函数调用和传递参数,就只能由系统在启动运行时传递参数了;
在编译连接好得到一个可执行文件test.exe后,将在系统执行这个可执行文件时,将参数一起传入,./test.exe a b c d
a b c d 分别为四个参数,其关系为 :
argc = 5
argv[0]=./test.exe
argv[1]=a
argv[2]=b
argv[3]=c
argv[4]=d
前面介绍的main函数都是不带参数的。因此main 后的括号都是空括号。实际上,main函数可以带参数,这个参数可以认为是 main函数的形式参数。C语言规定main函数的参数只能有两个, 习惯上这两个参数写为argc和argv。因此,main函数的函数头可写为: main (argc,argv)C语言还规定argc(第一个形参)必须是整型变量,argv( 第二个形参)必须是指向字符串的指针数组。加上形参说明后,main函数的函数头应写为:
main (argc,argv)
int argv;
char *argv[];或写成:
main (int argc,char *argv[])
由于main函数不能被其它函数调用, 因此不可能在程序内部取得实际值。那么,在何处把实参值赋予main函数的形参呢? 实际上,main函数的参数值是从操作系统命令行上获得的。当我们要运行一个可执行文件时,在DOS提示符下键入文件名,再输入实际参数即可把这些实参传送到main的形参中去。
DOS提示符下命令行的一般形式为: C:\>可执行文件名 参数 参数……; 但是应该特别注意的是,main 的两个形参和命令行中的参数在
位置上不是一一对应的。因为,main的形参只有二个,而命令行中的参数个数原则上未加限制。argc参数表示了命令行中参数的个数(注意:文件名本身也算一个参数),argc的值是在输入命令行时由系统按实际参数的个数自动赋予的。例如有命令行为: C:\>E6 24 BASIC dbase FORTRAN由于文件名E6 24本身也算一个参数,所以共有4个参数,因此argc取得的值为4。argv参数是字符串指针数组,其各元素值为命令行中各字符串(参数均按字符串处理)的首地址。 指针数组的长度即为参数个数。数组元素初值由系统自动赋予。其表示如图6.8所示:
main(int argc,char *argv){
while(argc-->1)
printf("%s\n",*++argv);
}
本例是显示命令行中输入的参数如果上例的可执行文件名为e24.exe,存放在A驱动器的盘内。
因此输入的命令行为: C:\>a:e24 BASIC dBASE FORTRAN
则运行结果为:
BASIC
dBASE
FORTRAN
该行共有4个参数,执行main时,argc的初值即为4。argv的4个元素分为4个字符串的首地址。执行while语句,每循环一次 argv值减1,当argv等于1时停止循环,共循环三次, 因此共可输出三个参数。在printf函数中,由于打印项*++argv是先加1再打印, 故第一次打印的是argv[1]所指的字符串BASIC。第二、 三次循环分别打印后二个字符串。而参数e24是文件名,不必输出。
下例的命令行中有两个参数,第二个参数20即为输入的n值。在程序中*++argv的值为字符串“20”,然后用函数"atoi"把它换为整型作为while语句中的循环控制变量,输出20个偶数。
#include"stdlib.h"
main(int argc,char*argv[]){
int a=0,n;
n=atoi(*++argv);
while(n--) printf("%d ",a++*2);
}
本程序是从0开始输出n个偶数。指向指针的指针变量如果一个指针变量存放的又是另一个指针变量的地址, 则称这个指针变量为指向指针的指针变量。
Friday, November 18, 2011
教你怎么关闭Win7用户帐户控制
具体方法如下:单击屏幕左下角的 Windows 徽标打开开始菜单-“控制面板”-“用户账户和家庭安全”-“用户帐户”-“更改用户账户控制设置”,进入后将滑块下移到底,重启后即可关闭。
Thursday, November 17, 2011
内存分配方式
(1) 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的
整个运行期间都存在。例如全局变量,static 变量。
(2) 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函
数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集
中,效率很高,但是分配的内存容量有限。
(3) 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc 或new 申请任意多
少的内存,程序员自己负责在何时用free 或delete 释放内存。动态内存的生存期
由我们决定,使用非常灵活,但问题也最多。
整个运行期间都存在。例如全局变量,static 变量。
(2) 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函
数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集
中,效率很高,但是分配的内存容量有限。
(3) 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc 或new 申请任意多
少的内存,程序员自己负责在何时用free 或delete 释放内存。动态内存的生存期
由我们决定,使用非常灵活,但问题也最多。
关于C语言编程中include的用法
文件包含命令行的一般形式为:
#include"文件名"
文件包含命令的功能是把指定的文件插入该命令行位置取代该命令行,从而把指定的文件和当前的源程序文件连成一个源文件。
在程序设计中,文件包含是很有用的。一个大的程序可以分为多个模块,由多个程序员分别编程。有些公用的符号常量或宏定义等可单独组成一个文件,在其它文件的开头用包含命令包含该文件即可使用。这样,可避免在每个文件开头都去书写那些公用量,从而节省时间,并减少出错。
对文件包含命令还要说明以下几点:
1. 包含命令中的文件名可以用双引号括起来,也可以用尖括号括起来。例如以下写法都是允许的:
#include"stdio.h"
#include
但是这两种形式是有区别的:使用尖括号表示在包含文件目录中去查找(包含目录是由用户在设置环境时设置的),而不在源文件目录去查找.使用双引号则表示首先在当前的源文件目录中查找,若未找到才到包含目录中去查找。用户编程时可根据自己文件所在的目录来选择某一种命令形式。
2. 一个include命令只能指定一个被包含文件,若有多个文件要包含,则需用多个include命令。
3. 文件包含允许嵌套,即在一个被包含的文件中又可以包含另一个文件。
#include"文件名"
文件包含命令的功能是把指定的文件插入该命令行位置取代该命令行,从而把指定的文件和当前的源程序文件连成一个源文件。
在程序设计中,文件包含是很有用的。一个大的程序可以分为多个模块,由多个程序员分别编程。有些公用的符号常量或宏定义等可单独组成一个文件,在其它文件的开头用包含命令包含该文件即可使用。这样,可避免在每个文件开头都去书写那些公用量,从而节省时间,并减少出错。
对文件包含命令还要说明以下几点:
1. 包含命令中的文件名可以用双引号括起来,也可以用尖括号括起来。例如以下写法都是允许的:
#include"stdio.h"
#include
但是这两种形式是有区别的:使用尖括号表示在包含文件目录中去查找(包含目录是由用户在设置环境时设置的),而不在源文件目录去查找.使用双引号则表示首先在当前的源文件目录中查找,若未找到才到包含目录中去查找。用户编程时可根据自己文件所在的目录来选择某一种命令形式。
2. 一个include命令只能指定一个被包含文件,若有多个文件要包含,则需用多个include命令。
3. 文件包含允许嵌套,即在一个被包含的文件中又可以包含另一个文件。
HP ZR22W显示器的高度调节
说明书上,以及网上都没有写清楚对于这款显示器如何调节高度。
在支柱的背后有一个按钮,刚买来的时候这个按钮是按不动的,需要轻轻把显示器向下按一下,这个按钮就可以按动了,然后显示器会弹出很高。当你把显示器与这个stand连接在一起的时候,就自然可以调节显示器的高度了。
在支柱的背后有一个按钮,刚买来的时候这个按钮是按不动的,需要轻轻把显示器向下按一下,这个按钮就可以按动了,然后显示器会弹出很高。当你把显示器与这个stand连接在一起的时候,就自然可以调节显示器的高度了。
Monday, November 7, 2011
如何在苹果系统下打开俄文的IAC的说明文件
File > Open > Plain Text Encoding
Can you really not find Cyrillic (Windows) in the list? If not, go the bottom where it says Customize Encodings List and add it.
TextEdit > Preferences > Open and Save > Plain Text File Encoding > Opening Files
Can you really not find Cyrillic (Windows) in the list? If not, go the bottom where it says Customize Encodings List and add it.
TextEdit > Preferences > Open and Save > Plain Text File Encoding > Opening Files
Subscribe to:
Posts (Atom)