﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-冰山上的狼-随笔分类-C++</title><link>http://www.cppblog.com/paladino/category/4424.html</link><description>在努力、磨练、打击下不断地向着理想前进</description><language>zh-cn</language><lastBuildDate>Mon, 19 May 2008 12:46:14 GMT</lastBuildDate><pubDate>Mon, 19 May 2008 12:46:14 GMT</pubDate><ttl>60</ttl><item><title>C++复习：C基础(结构+联合)</title><link>http://www.cppblog.com/paladino/archive/2007/06/19/26614.html</link><dc:creator>Gu.paladino</dc:creator><author>Gu.paladino</author><pubDate>Tue, 19 Jun 2007 03:29:00 GMT</pubDate><guid>http://www.cppblog.com/paladino/archive/2007/06/19/26614.html</guid><wfw:comment>http://www.cppblog.com/paladino/comments/26614.html</wfw:comment><comments>http://www.cppblog.com/paladino/archive/2007/06/19/26614.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/paladino/comments/commentRss/26614.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/paladino/services/trackbacks/26614.html</trackback:ping><description><![CDATA[Ｃ语言中给出了另一种构造数据类型——&#8220;结构&#8221;。 它相当于其它高级语言中的记录。&#8220;结构&#8221;是一种构造类型，它是由若干&#8220;成员&#8221;组成的。 每一个成员可以是一个基本数据类型或者又是一个构造类型。 结构既是一种&#8220;构造&#8221;而成的数据类型， 那么在说明和使用之前必须先定义它，也就是构造它。如同在说明和调用函数之前要先定义函数一样。<br><br>一、结构的定义<br>定义一个结构的一般形式为： <br>struct 结构名 <br>{ <br>&nbsp;&nbsp; &nbsp;成员表列 <br>};<br>成员表由若干个成员组成， 每个成员都是该结构的一个组成部分。对每个成员也必须作类型说明，其形式为：<br>类型说明符 成员名; <br>成员名的命名应符合标识符的书写规定。<br>说明结构变量有以下三种方法。以上面定义的stu为例来加以说明。<br>1. 先定义结构，再说明结构变量。如： <br>struct stu<br>{<br>&nbsp;&nbsp; &nbsp;int num;<br>&nbsp;&nbsp; &nbsp;char name[20];<br>&nbsp;&nbsp; &nbsp;char sex;<br>&nbsp;&nbsp; &nbsp;float score;<br>};<br>struct stu boy1,boy2;<br>说明了两个变量boy1和boy2为stu结构类型。也可以用宏定义使一个符号常量来表示一个结构类型，例如： <br>#define STU struct stu<br>STU<br>{<br>&nbsp;&nbsp; &nbsp;int num;<br>&nbsp;&nbsp; &nbsp;char name[20];<br>&nbsp;&nbsp; &nbsp;char sex;<br>&nbsp;&nbsp; &nbsp;float score;<br>};<br>STU boy1,boy2;<br><br>2. 在定义结构类型的同时说明结构变量。例如： <br>struct stu<br>{<br>&nbsp;&nbsp; &nbsp;int num;<br>&nbsp;&nbsp; &nbsp;char name[20];<br>&nbsp;&nbsp; &nbsp;char sex;<br>&nbsp;&nbsp; &nbsp;float score;<br>}boy1,boy2;<br><br>3. 直接说明结构变量。例如： <br>struct<br>{<br>&nbsp;&nbsp; &nbsp;int num;<br>&nbsp;&nbsp; &nbsp;char name[20];<br>&nbsp;&nbsp; &nbsp;char sex;<br>&nbsp;&nbsp; &nbsp;float score;<br>}boy1,boy2; <br>　　第三种方法与第二种方法的区别在于第三种方法中省去了结构名，而直接给出结构变量。三种方法中说明的boy1,boy2变量都具有图7.1所示的结构。说明了boy1,boy2变量为stu类型后，即可向这两个变量中的各个成员赋值。在上述stu结构定义中，所有的成员都是基本数据类型或数组类型。成员也可以又是一个结构， 即构成了嵌套的结构。例如，图7.2给出了另一个数据结构。<br>在ANSI C中除了允许具有相同类型的结构变量相互赋值以外， 一般对结构变量的使用，包括赋值、输入、输出、 运算等都是通过结构变量的成员来实现的。<br>　　表示结构变量成员的一般形式是： 结构变量名.成员名<br>如果结构变量是全局变量或为静态变量， 则可对它作初始化赋值。对局部或自动结构变量不能作初始化赋值。<br>数组的元素也可以是结构类型的。 因此可以构成结构型数组。结构数组的每一个元素都是具有相同结构类型的下标结构变量。<br><br>结构指针变量的说明和使用一个指针变量当用来指向一个结构变量时， 称之为结构指针变量。<br>结构指针变量中的值是所指向的结构变量的首地址。 通过结构指针即可访问该结构变量， 这与数组指针和函数指针的情况是相同的。结构指针变量说明的一般形式为： <br>struct 结构名*结构指针变量名<br>struct stu *pstu;<br><br>当然也可在定义stu结构时同时说明pstu。与前面讨论的各类指针变量相同，结构指针变量也必须要先赋值后才能使用。赋值是把结构变量的首地址赋予该指针变量， 不能把结构名赋予该指针变量。如果boy是被说明为stu类型的结构变量，则： pstu=&amp;boy是正确的，而： pstu=&amp;stu是错误的。<br><br>　　结构名和结构变量是两个不同的概念，不能混淆。 结构名只能表示一个结构形式，编译系统并不对它分配内存空间。 只有当某变量被说明为这种类型的结构时，才对该变量分配存储空间。 因此上面&amp;stu这种写法是错误的，不可能去取一个结构名的首地址。 有了结构指针变量，就能更方便地访问结构变量的各个成员。<br><br>其访问的一般形式为： (*结构指针变量).成员名 或为：<br>结构指针变量-&gt;成员名 <br>例如： (*pstu).num或者： pstu-&gt;num<br>应该注意(*pstu)两侧的括号不可少， 因为成员符&#8220;.&#8221;的优先级高于&#8220;*&#8221;。如去掉括号写作*pstu.num则等效于*(pstu.num)，这样，意义就完全不对了。<br><br>结构变量.成员名<br>(*结构指针变量).成员名<br>结构指针变量-&gt;成员名 <br>　　这三种用于表示结构成员的形式是完全等效的。结构数组指针变量结构指针变量可以指向一个结构数组， 这时结构指针变量的值是整个结构数组的首地址。 结构指针变量也可指向结构数组的一个元素，这时结构指针变量的值是该结构数组元素的首地址。设ps为指向结构数组的指针变量，则ps也指向该结构数组的0号元素，ps+1指向1号元素，ps+i则指向i号元素。 这与普通数组的情况是一致的。<br><br><br>Ｃ语言中不允许动态数组类型。例如： int n;scanf("%d",&amp;n);int a[n]; 用变量表示长度，想对数组的大小作动态说明， 这是错误的。但是在实际的编程中，往往会发生这种情况， 即所需的内存空间取决于实际输入的数据，而无法预先确定。对于这种问题， 用数组的办法很难解决。为了解决上述问题，Ｃ语言提供了一些内存管理函数，这些内存管理函数可以按需要动态地分配内存空间， 也可把不再使用的空间回收待用，为有效地利用内存资源提供了手段。 常用的内存管理函数有以下三个：<br>1.分配内存空间函数malloc<br>调用形式： (类型说明符*) malloc (size) 功能：在内存的动态存储区中分配一块长度为"size" 字节的连续区域。函数的返回值为该区域的首地址。 &#8220;类型说明符&#8221;表示把该区域用于何种数据类型。(类型说明符*)表示把返回值强制转换为该类型指针。&#8220;size&#8221;是一个无符号数。例如： pc=(char *) malloc (100); 表示分配100个字节的内存空间，并强制转换为字符数组类型， 函数的返回值为指向该字符数组的指针， 把该指针赋予指针变量pc。<br>2.分配内存空间函数 calloc<br>calloc 也用于分配内存空间。调用形式： (类型说明符*)calloc(n,size) 功能：在内存动态存储区中分配n块长度为&#8220;size&#8221;字节的连续区域。函数的返回值为该区域的首地址。(类型说明符*)用于强制类型转换。calloc函数与malloc 函数的区别仅在于一次可以分配n块区域。例如： ps=(struet stu*) calloc(2,sizeof (struct stu)); 其中的sizeof(struct stu)是求stu的结构长度。因此该语句的意思是：按stu的长度分配2块连续区域，强制转换为stu类型，并把其首地址赋予指针变量ps。<br>3.释放内存空间函数free<br>调用形式： free(void*ptr); 功能：释放ptr所指向的一块内存空间，ptr 是一个任意类型的指针变量，它指向被释放区域的首地址。被释放区应是由malloc或calloc函数所分配的区域。<br><br><br>&#8220;联合&#8221;与&#8220;结构&#8221;有一些相似之处。但两者有本质上的不同。在结构中各成员有各自的内存空间， 一个结构变量的总长度是各成员长度之和。而在&#8220;联合&#8221;中，各成员共享一段内存空间， 一个联合变量的长度等于各成员中最长的长度。应该说明的是， 这里所谓的共享不是指把多个成员同时装入一个联合变量内， 而是指该联合变量可被赋予任一成员值，但每次只能赋一种值， 赋入新值则冲去旧值。如前面介绍的&#8220;单位&#8221;变量， 如定义为一个可装入&#8220;班级&#8221;或&#8220;教研室&#8221;的联合后，就允许赋予整型值（班级)或字符串（教研室)。要么赋予整型值，要么赋予字符串，不能把两者同时赋予它。联合类型的定义和联合变量的说明一个联合类型必须经过定义之后， 才能把变量说明为该联合类型。<br>一、联合的定义<br>定义一个联合类型的一般形式为： <br>union 联合名 <br>{ <br>&nbsp;&nbsp; &nbsp;成员表 <br>};<br>成员表中含有若干成员，成员的一般形式为： 类型说明符 成员名 成员名的命名应符合标识符的规定。<br><br>小结<br>1. 结构和联合是两种构造类型数据，是用户定义新数据类型的重要手段。结构和联合有很多的相似之处，它们都由成员组成。成员可以具有不同的数据类型。成员的表示方法相同。都可用三种方式作变量说明。<br>2. 在结构中，各成员都占有自己的内存空间，它们是同时存在的。一个结构变量的总长度等于所有成员长度之和。在联合中，所有成员不能同时占用它的内存空间，它们不能同时存在。联合变量的长度等于最长的成员的长度。<br>3. &#8220;.&#8221;是成员运算符，可用它表示成员项，成员还可用&#8220;-&gt;&#8221;运算符来表示。<br>4. 结构变量可以作为函数参数，函数也可返回指向结构的指针变量。而联合变量不能作为函数参数，函数也不能返回指向联合的指针变量。但可以使用指向联合变量的指针，也可使用联合数组。<br>5. 结构定义允许嵌套，结构中也可用联合作为成员，形成结构和联合的嵌套。<br>6. 链表是一种重要的数据结构，它便于实现动态的存储分配。本章介绍是单向链表，还可组成双向链表，循环链表等。
<br><img src ="http://www.cppblog.com/paladino/aggbug/26614.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/paladino/" target="_blank">Gu.paladino</a> 2007-06-19 11:29 <a href="http://www.cppblog.com/paladino/archive/2007/06/19/26614.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++复习：C基础(指针)</title><link>http://www.cppblog.com/paladino/archive/2007/06/19/26613.html</link><dc:creator>Gu.paladino</dc:creator><author>Gu.paladino</author><pubDate>Tue, 19 Jun 2007 03:28:00 GMT</pubDate><guid>http://www.cppblog.com/paladino/archive/2007/06/19/26613.html</guid><wfw:comment>http://www.cppblog.com/paladino/comments/26613.html</wfw:comment><comments>http://www.cppblog.com/paladino/archive/2007/06/19/26613.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/paladino/comments/commentRss/26613.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/paladino/services/trackbacks/26613.html</trackback:ping><description><![CDATA[为了正确地访问内存单元，必须为每个内存单元编上号。根据一个内存单元的编号即可准确地找到该内存单元。内存单元的编号也叫做地址。既然根据内存单元的编号或地址就可以找到所需的内存单元，所以通常也把这个地址称为指针。内存单元的指针和内存单元的内容是两个不同的概念。<br><br>对于一个内存单元来说，单元的地址即为指针， 其中存放的数据才是该单元的内容。在Ｃ语言中， 允许用一个变量来存放指针，这种变量称为指针变量。因此， 一个指针变量的值就是某个内存单元的地址或称为某内存单元的指针。<br><br>严格地说，一个指针是一个地址， 是一个常量。而一个指针变量却可以被赋予不同的指针值，是变量。既然指针变量的值是一个地址，那么这个地址不仅可以是变量的地址，也可以是其它数据结构的地址。在一个指针变量中存放一个数组或一个函数的首地址有何意义呢？ 因为数组或函数都是连续存放的。通过访问指针变量取得了数组或函数的首地址， 也就找到了该数组或函数。这样一来，凡是出现数组，函数的地方都可以用一个指针变量来表示，只要该指针变量中赋予数组或函数的首地址即可。这样做，将会使程序的概念十分清楚，程序本身也精练，高效。在Ｃ语言中，一种数据类型或数据结构往往都占有一组连续的内存单元。 用&#8220;地址&#8221;这个概念并不能很好地描述一种数据类型或数据结构，而&#8220;指针&#8221;虽然实际上也是一个地址，但它却是一个数据结构的首地址，它是&#8220;指向&#8221;一个数据结构的，因而概念更为清楚，表示更为明确。这也是引入&#8220;指针&#8221;概念的一个重要原因。<br><br>对指针变量的类型说明包括三个内容：<br>(1)指针类型说明，即定义变量为一个指针变量； <br>(2)指针变量名；<br>(3)变量值(指针)所指向的变量的数据类型。<br>　　其一般形式为： 类型说明符 *变量名； <br>　　其中，*表示这是一个指针变量，变量名即为定义的指针变量名，类型说明符表示本指针变量所指向的变量的数据类型。<br>应该注意的是，一个指针变量只能指向同类型的变量，如float *p只能指向浮点变量，不能时而指向一个浮点变量， 时而又指向一个字符变量。<br><br>指针变量同普通变量一样，使用之前不仅要定义说明， 而且必须赋予具体的值。未经赋值的指针变量不能使用， 否则将造成系统混乱，甚至死机。指针变量的赋值只能赋予地址， 决不能赋予任何其它数据，否则将引起错误。在Ｃ语言中， 变量的地址是由编译系统分配的，对用户完全透明，用户不知道变量的具体地址。 Ｃ语言中提供了地址运算符&amp;来表示变量的地址。其一般形式为： &amp; 变量名； 如&amp;a变示变量a的地址，&amp;b表示变量b的地址。 变量本身必须预先说明。<br><br>指针变量可以进行某些运算，但其运算的种类是有限的。 它只能进行赋值运算和部分算术运算及关系运算。<br>1.指针运算符<br>(1)取地址运算符&amp;<br>　　取地址运算符&amp;是单目运算符，其结合性为自右至左，其功能是取变量的地址。<br>(2)取内容运算符*<br>　　取内容运算符*是单目运算符，其结合性为自右至左，用来表示指针变量所指的变量。在*运算符之后跟的变量必须是指针变量。需要注意的是指针运算符*和指针变量说明中的指针说明符* 不是一回事。在指针变量说明中，&#8220;*&#8221;是类型说明符，表示其后的变量是指针类型。而表达式中出现的&#8220;*&#8221;则是一个运算符用以表示指针变量所指的变量。<br><br>使用字符串指针变量与字符数组的区别<br>用字符数组和字符指针变量都可实现字符串的存储和运算。 但是两者是有区别的。在使用时应注意以下几个问题：<br>1. 字符串指针变量本身是一个变量，用于存放字符串的首地址。而字符串本身是存放在以该首地址为首的一块连续的内存空间中并以&#8216;\0&#8217;作为串的结束。字符数组是由于若干个数组元素组成的，它可用来存放整个字符串。<br>2. 对字符数组作初始化赋值，必须采用外部类型或静态类型，如： static char st[]={&#8220;C Language&#8221;};而对字符串指针变量则无此限制，如： char *ps="C Language";<br>3. 对字符串指针方式 char *ps="C Language";可以写为： char *ps;　ps="C Language";而对数组方式： <br>static char st[]={"C Language"};<br>不能写为：<br>char st[20];st={"C Language"};<br>而只能对字符数组的各元素逐个赋值。<br>　　从以上几点可以看出字符串指针变量与字符数组在使用时的区别，同时也可看出使用指针变量更加方便。前面说过，当一个指针变量在未取得确定地址前使用是危险的，容易引起错误。但是对指针变量直接赋值是可以的。因为C系统对指针变量赋值时要给以确定的地址。因此， <br>char *ps="C Langage";<br>或者 char *ps;<br>ps="C Language";都是合法的。<br><br>函数指针变量<br>在Ｃ语言中规定，一个函数总是占用一段连续的内存区， 而函数名就是该函数所占内存区的首地址。 我们可以把函数的这个首地址(或称入口地址)赋予一个指针变量， 使该指针变量指向该函数。然后通过指针变量就可以找到并调用这个函数。 我们把这种指向函数的指针变量称为&#8220;函数指针变量&#8221;。<br>函数指针变量定义的一般形式为：<br>类型说明符 (*指针变量名)(); <br>其中&#8220;类型说明符&#8221;表示被指函数的返回值的类型。&#8220;(* 指针变量名)&#8221;表示&#8220;*&#8221;后面的变量是定义的指针变量。 最后的空括号表示指针变量所指的是一个函数。<br>使用函数指针变量还应注意以下两点：<br>a. 函数指针变量不能进行算术运算，这是与数组指针变量不同的。数组指针变量加减一个整数可使指针移动指向后面或前面的数组元素，而函数指针的移动是毫无意义的。<br>b. 函数调用中"(*指针变量名)"的两边的括号不可少，其中的*不应该理解为求值运算，在此处它只是一种表示符号。<br><br><br>指针型函数<br>所谓函数类型是指函数返回值的类型。 在Ｃ语言中允许一个函数的返回值是一个指针(即地址)， 这种返回指针值的函数称为指针型函数。<br>定义指针型函数的一般形式为： <br>类型说明符 *函数名(形参表) <br>{ <br>&#8230;&#8230; /*函数体*/<br>} <br>其中函数名之前加了&#8220;*&#8221;号表明这是一个指针型函数，即返回值是一个指针。类型说明符表示了返回的指针值所指向的数据类型。<br><br>main函数可以带参数，这个参数可以认为是 main函数的形式参数。Ｃ语言规定main函数的参数只能有两个， 习惯上这两个参数写为argc和argv。因此，main函数的函数头可写为： main (argc,argv)Ｃ语言还规定argc(第一个形参)必须是整型变量,argv( 第二个形参)必须是指向字符串的指针数组。加上形参说明后，main函数的函数头应写为： <br>main (argc,argv)<br>int argv;<br>char *argv[];或写成：<br>main (int argc,char *argv[])<br>　　由于main函数不能被其它函数调用， 因此不可能在程序内部取得实际值。那么，在何处把实参值赋予main函数的形参呢? 实际上,main函数的参数值是从操作系统命令行上获得的。当我们要运行一个可执行文件时，在DOS提示符下键入文件名，再输入实际参数即可把这些实参传送到main的形参中去。<br><br>通过指针访问变量称为间接访问， 简称间访。由于指针变量直接指向变量，所以称为单级间访。 而如果通过指向指针的指针变量来访问变量则构成了二级或多级间访。在Ｃ语言程序中，对间访的级数并未明确限制， 但是间访级数太多时不容易理解解，也容易出错，因此，一般很少超过二级间访。 指向指针的指针变量说明的一般形式为： <br>类型说明符** 指针变量名；<br><br>小结<br>1. 指针是Ｃ语言中一个重要的组成部分，使用指针编程有以下优点：<br>(1)提高程序的编译效率和执行速度。<br>(2)通过指针可使用主调函数和被调函数之间共享变量或数据结构，便于实现双向数据通讯。<br>(3)可以实现动态的存储分配。<br>(4)便于表示各种数据结构，编写高质量的程序。<br><br>2. 指针的运算<br>(1)取地址运算符&amp;：求变量的地址<br>(2)取内容运算符*：表示指针所指的变量<br>(3)赋值运算<br>&#183;把变量地址赋予指针变量<br>&#183;同类型指针变量相互赋值<br>&#183;把数组，字符串的首地址赋予指针变量<br>&#183;把函数入口地址赋予指针变量<br>(4)加减运算<br>对指向数组，字符串的指针变量可以进行加减运算，如p+n,p-n,p++,p--等。对指向同一数组的两个指针变量可以相减。对指向其它类型的指针变量作加减运算是无意义的。 <br>(5)关系运算<br>指向同一数组的两个指针变量之间可以进行大于、小于、 等于比较运算。指针可与0比较，p==0表示p为空指针。<br><br>3. 与指针有关的各种说明和意义见下表。<br>int *p; 　　　 p为指向整型量的指针变量<br>int *p[n]; 　　p为指针数组，由n个指向整型量的指针元素组成。<br>int (*p)[n]; 　p为指向整型二维数组的指针变量，二维数组的列数为n<br>int *p() 　　　p为返回指针值的函数，该指针指向整型量<br>int (*p)() 　　p为指向函数的指针，该函数返回整型量<br>int **p 　　　 p为一个指向另一指针的指针变量，该指针指向一个整型量。<br><br>4. 有关指针的说明很多是由指针，数组，函数说明组合而成的。<br>但并不是可以任意组合，例如数组不能由函数组成，即数组元素不能是一个函数；函数也不能返回一个数组或返回另一个函数。例如<br>int a[5]()；就是错误的。<br><br>5. 关于括号<br>在解释组合说明符时， 标识符右边的方括号和圆括号优先于标识符左边的&#8220;*&#8221;号，而方括号和圆括号以相同的优先级从左到右结合。但可以用圆括号改变约定的结合顺序。<br><br>6. 阅读组合说明符的规则是&#8220;从里向外&#8221;。<br>从标识符开始，先看它右边有无方括号或园括号，如有则先作出解释，再看左边有无*号。 如果在任何时候遇到了闭括号，则在继续之前必须用相同的规则处理括号内的内容。例如： <br>int*(*(*a)())[10]<br>&#8593; &#8593;&#8593;&#8593;&#8593;&#8593;&#8593;<br>7 6 4 2 1 3 5<br>上面给出了由内向外的阅读顺序，下面来解释它：<br>(1)标识符a被说明为；<br>(2)一个指针变量，它指向；<br>(3)一个函数，它返回；<br>(4)一个指针，该指针指向；<br>(5)一个有10个元素的数组，其类型为；<br>(6)指针型，它指向；<br>(7)int型数据。<br>因此a是一个函数指针变量，该函数返回的一个指针值又指向一个指针数组，该指针数组的元素指向整型量。<br><br>
<br><img src ="http://www.cppblog.com/paladino/aggbug/26613.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/paladino/" target="_blank">Gu.paladino</a> 2007-06-19 11:28 <a href="http://www.cppblog.com/paladino/archive/2007/06/19/26613.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++复习：C基础(数组+函数)</title><link>http://www.cppblog.com/paladino/archive/2007/06/18/26549.html</link><dc:creator>Gu.paladino</dc:creator><author>Gu.paladino</author><pubDate>Mon, 18 Jun 2007 02:14:00 GMT</pubDate><guid>http://www.cppblog.com/paladino/archive/2007/06/18/26549.html</guid><wfw:comment>http://www.cppblog.com/paladino/comments/26549.html</wfw:comment><comments>http://www.cppblog.com/paladino/archive/2007/06/18/26549.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/paladino/comments/commentRss/26549.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/paladino/services/trackbacks/26549.html</trackback:ping><description><![CDATA[　　数组在程序设计中，为了处理方便， 把具有相同类型的若干变量按有序的形式组织起来。这些按序排列的同类数据元素的集合称为数组。<br><br>&nbsp;&nbsp;&nbsp; 在Ｃ语言中， 数组属于构造数据类型。一个数组可以分解为多个数组元素，这些数组元素可以是基本数据类型或是构造类型。因此按数组元素的类型不同，数组又可分为数值数组、字符数组、指针数组、结构数组等各种类别。<br><br>数组说明的一般形式为： <br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;类型说明符 数组名 [常量表达式]，&#8230;&#8230;； <br>其中，类型说明符是任一种基本数据类型或构造数据类型。 数组名是用户定义的数组标识符。 方括号中的常量表达式表示数据元素的个数，也称为数组的长度。<br><br>对于数组类型说明应注意：<br>数组的类型实际上是指数组元素的取值类型。对于同一个数组，其所有元素的数据类型都是相同的。数组名的书写规则应符合标识符的书写规定。数组名不能与其它变量名相同。方括号中常量表达式表示数组元素的个数。不能在方括号中用变量来表示元素的个数， 但是可以是符号常数或常量表达式。允许在同一个类型说明中，说明多个数组和多个变量。<br><br>C语言对数组的初始赋值还有以下几点规定：<br>可以只给部分元素赋初值。当{ }中值的个数少于元素个数时，只给前面部分元素赋值。<br>例如static int a[10]={0,1,2,3,4};表示只给a[0]～a[4]5个元素赋值，而后5个元素自动赋0值。<br>只能给元素逐个赋值，不能给数组整体赋值。<br>例如给十个元素全部赋1值，只能写为： static int a[10]={1,1,1,1,1,1,1,1,1,1};而不能写为：static int a[10]=1;<br>如不给可初始化的数组赋初值，则全部元素均为0值。<br>如给全部元素赋值，则在数组说明中， 可以不给出数组元素的个数。<br>例如static int a[5]={1,2,3,4,5};可写为： static int a[]={1,2,3,4,5};动态赋值可以在程序执行过程中，对数组作动态赋值。 这时可用循环语句配合scanf函数逐个对数组元素赋值。<br><br>字符数组:用来存放字符量的数组称为字符数组。字符数组类型说明的形式与前面介绍的数值数组相同。<br>Ｃ语言允许用字符串的方式对数组作初始化赋值。用字符串方式赋值比用字符逐个赋值要多占一个字节， 用于存放字符串结束标志'\0'。<br><br><br>函数<br>Ｃ源程序是由函数组成的。 虽然在前面各章的程序中都只有一个主函数main()， 但实用程序往往由多个函数组成。函数是Ｃ源程序的基本模块， 通过对函数模块的调用实现特定的功能。<br>从函数定义的角度看，函数可分为库函数和用户定义函数两种。<br>库函数由Ｃ系统提供，用户无须定义， 也不必在程序中作类型说明，只需在程序前包含有该函数原型的头文件即可在程序中直接调用。<br>用户定义函数由用户按需要写的函数。对于用户自定义函数， 不仅要在程序中定义函数本身， 而且在主调函数模块中还必须对该被调函数进行类型说明，然后才能使用。<br><br>Ｃ语言的函数兼有其它语言中的函数和过程两种功能，从这个角度看，又可把函数分为有返回值函数和无返回值函数两种。有返回值函数，此类函数被调用执行完后将向调用者返回一个执行结果， 称为函数返回值。如数学函数即属于此类函数。 由用户定义的这种要返回函数值的函数，必须在函数定义和函数说明中明确返回值的类型。无返回值函数，此类函数用于完成某项特定的处理任务， 执行完成后不向调用者返回函数值。这类函数类似于其它语言的过程。 由于函数无须返回值，用户在定义此类函数时可指定它的返回为&#8220;空类型&#8221;， 空类型的说明符为&#8220;void&#8221;。<br><br>从主调函数和被调函数之间数据传送的角度看又可分为无参函数和有参函数两种。<br>无参函数，函数定义、函数说明及函数调用中均不带参数。 主调函数和被调函数之间不进行参数传送。 此类函数通常用来完成一组指定的功能，可以返回或不返回函数值。有参函数，也称为带参函数。在函数定义及函数说明时都有参数， 称为形式参数(简称为形参)。在函数调用时也必须给出参数， 称为实际参数(简称为实参)。 进行函数调用时，主调函数将把实参的值传送给形参，供被调函数使用。<br><br><br>Ｃ语言提供了极为丰富的库函数， 这些库函数又可从功能角度作以下分类。<br>(1)字符类型分类函数<br>　　用于对字符按ASCII码分类：字母，数字，控制字符，分隔符，大小写字母等。<br>(2)转换函数<br>　　用于字符或字符串的转换；在字符量和各类数字量 (整型， 实型等)之间进行转换；在大、小写之间进行转换。<br>(3)目录路径函数<br>　　用于文件目录和路径操作。<br>(4)诊断函数<br>　　用于内部错误检测。<br>(5)图形函数<br>　　用于屏幕管理和各种图形功能。 <br>(6)输入输出函数<br>　　用于完成输入输出功能。<br>(7)接口函数<br>　　用于与DOS，BIOS和硬件的接口。<br>(8)字符串函数 <br>　　用于字符串操作和处理。<br>(9)内存管理函数<br>　　用于内存管理。<br>(10)数学函数<br>　　用于数学函数计算。<br>(11)日期和时间函数<br>　　用于日期，时间转换操作。<br>(12)进程控制函数<br>　　用于进程管理和控制。<br>(13)其它函数<br>　　用于其它各种功能。<br><br>Ｃ语言中，所有的函数定义，包括主函数main在内，都是平行的。也就是说，在一个函数的函数体内， 不能再定义另一个函数， 即不能嵌套定义。但是函数之间允许相互调用，也允许嵌套调用。习惯上把调用者称为主调函数。 函数还可以自己调用自己，称为递归调用。main 函数是主函数，它可以调用其它函数，而不允许被其它函数调用。 因此，Ｃ程序的执行总是从main函数开始， 完成对其它函数的调用后再返回到main函数，最后由main函数结束整个程序。一个Ｃ源程序必须有，也只能有一个主函数main。<br><br>函数的参数分为形参和实参两种。形参出现在函数定义中，在整个函数体内都可以使用， 离开该函数则不能使用。实参出现在主调函数中，进入被调函数后，实参变量也不能使用。 形参和实参的功能是作数据传送。发生函数调用时， 主调函数把实参的值传送给被调函数的形参从而实现主调函数向被调函数的数据传送。<br><br>函数的形参和实参具有以下特点：<br>1.形参变量只有在被调用时才分配内存单元，在调用结束时， 即刻释放所分配的内存单元。因此，形参只有在函数内部有效。 函数调用结束返回主调函数后则不能再使用该形参变量。<br>2.实参可以是常量、变量、表达式、函数等， 无论实参是何种类型的量，在进行函数调用时，它们都必须具有确定的值， 以便把这些值传送给形参。 因此应预先用赋值，输入等办法使实参获得确定值。<br>3.实参和形参在数量上，类型上，顺序上应严格一致， 否则会发生&#8220;类型不匹配&#8221;的错误。<br>4.函数调用中发生的数据传送是单向的。 即只能把实参的值传送给形参，而不能把形参的值反向地传送给实参。 因此在函数调用过程中，形参的值发生改变，而实参中的值不会变化。实参的值不随形参的变化而变化。<br><br>用数组名作函数参数与用数组元素作实参有几点不同：<br>1. 用数组元素作实参时，只要数组类型和函数的形参变量的类型一致，那么作为下标变量的数组元素的类型也和函数形参变量的类型是一致的。因此， 并不要求函数的形参也是下标变量。 换句话说，对数组元素的处理是按普通变量对待的。用数组名作函数参数时， 则要求形参和相对应的实参都必须是类型相同的数组，都必须有明确的数组说明。当形参和实参二者不一致时，即会发生错误。<br><br>2. 在普通变量或下标变量作函数参数时，形参变量和实参变量是由编译系统分配的两个不同的内存单元。在函数调用时发生的值传送是把实参变量的值赋予形参变量。在用数组名作函数参数时，不是进行值的传送，即不是把实参数组的每一个元素的值都赋予形参数组的各个元素。因为实际上形参数组并不存在，编译系统不为形参数组分配内存。那么，数据的传送是如何实现的呢? 在第四章中我们曾介绍过，数组名就是数组的首地址。因此在数组名作函数参数时所进行的传送只是地址的传送， 也就是说把实参数组的首地址赋予形参数组名。形参数组名取得该首地址之后，也就等于有了实在的数组。实际上是形参数组和实参数组为同一数组，共同拥有一段内存空间。<br><br>Ｃ语言中不允许作嵌套的函数定义。因此各函数之间是平行的，不存在上一级函数和下一级函数的问题。 但是Ｃ语言允许在一个函数的定义中出现对另一个函数的调用。 这样就出现了函数的嵌套调用。即在被调函数中又调用其它函数。 这与其它语言的子程序嵌套的情形是类似的。<br><br>一个函数在它的函数体内调用它自身称为递归调用。 这种函数称为递归函数。Ｃ语言允许函数的递归调用。在递归调用中， 主调函数又是被调函数。执行递归函数将反复调用其自身。 每调用一次就进入新的一层。<br><br><img src ="http://www.cppblog.com/paladino/aggbug/26549.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/paladino/" target="_blank">Gu.paladino</a> 2007-06-18 10:14 <a href="http://www.cppblog.com/paladino/archive/2007/06/18/26549.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++复习：C的基础知识</title><link>http://www.cppblog.com/paladino/archive/2007/06/18/26548.html</link><dc:creator>Gu.paladino</dc:creator><author>Gu.paladino</author><pubDate>Mon, 18 Jun 2007 02:13:00 GMT</pubDate><guid>http://www.cppblog.com/paladino/archive/2007/06/18/26548.html</guid><wfw:comment>http://www.cppblog.com/paladino/comments/26548.html</wfw:comment><comments>http://www.cppblog.com/paladino/archive/2007/06/18/26548.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/paladino/comments/commentRss/26548.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/paladino/services/trackbacks/26548.html</trackback:ping><description><![CDATA[main是主函数的函数名，表示这是一个主函数。每一个C源程序都必须有，且只能有一个主函数(main函数)。<br>include 称为文件包含命令，其意义是把尖括号(&lt;&gt;)或引号("")内指定的文件包含到本程序来，成为本程序的一部分。被包含的文件通常是由系统提供的，其扩展名为.h。因此也称为&lt;头文件&gt;或&lt;首部文件&gt;。<br>C语言的头文件中包括了各个标准库函数的函数原型。<br>C语言规定对scanf和printf这两个函数可以省去对其头文件的包含命令。<br><br>scanf和 printf这两个函数分别称为&#8220;格式输入函数&#8221;和&#8220;格式输出函数&#8221;。其意义是按指定的格式输入输出值。因此，这两个函数在括号中的参数表都由以下两部分组成：&#8220;格式控制串&#8221;，参数表。格式控制串是一个字符串，必须用双引号("")括起来，它表示了输入输出量的数据类型。在printf函数中还可以在格式控制串内出现非格式控制字符，这时在显示屏幕上将原文照印。参数表中给出了输入或输出的量。当有多个量时，用逗号间隔。<br><br>一个Ｃ语言源程序可以由一个或多个源文件组成。<br>每个源文件可由一个或多个函数组成。<br>一个源程序不论由多少个文件组成，都有一个且只能有一个main函数，即主函数。<br>源程序中可以有预处理命令(include 命令仅为其中的一种)，预处理命令通常应放在源文件或源程序的最前面。<br>每一个说明，每一个语句都必须以分号结尾。但预处理命令，函数头和花括号&#8220;}&#8221;之后不能加分号。<br>标识符，关键字之间必须至少加一个空格以示间隔。若已有明显的间隔符，也可不再加空格来间隔。<br><br>Ｃ语言字符集由字母，数字，空格，标点和特殊字符组成。在字符常量，字符串常量和注释中还可以使用汉字或其它可表示的图形符号。<br>1.字母　　小写字母a～z共26个，大写字母A～Z共26个<br>2.数字　　0～9共10个<br>3.空白符　空格符、制表符、换行符等统称为空白符。空白符只在字符常量和字符串常量中起作用。在其它地方出现时，只起间隔作用， 编译程序对它们忽略。因此在程序中使用空白符与否，对程序的编译不发生影响，但在程序中适当的地方使用空白符将增加程序的清晰性和可读性。<br><br>在Ｃ语言中使用的词汇分为六类：标识符，关键字，运算符，分隔符，常量，注释符等。<br>1.标识符——在程序中使用的变量名、函数名、标号等统称为标识符。除库函数的函数名由系统定义外，其余都由用户自定义。C 规定，标识符只能是字母(A～Z，a～z)、数字(0～9)、下划线()组成的字符串，并且其第一个字符必须是字母或下划线。在使用标识符时还必须注意：标准C不限制标识符的长度，但它受各种版本的C 语言编译系统限制，同时也受到具体机器的限制。例如在某版本C 中规定标识符前八位有效，当两个标识符前八位相同时，则被认为是同一个标识符。在标识符中，大小写是有区别的。例如BOOK和book 是两个不同的标识符。<br><br>2.关键字——关键字是由Ｃ语言规定的具有特定意义的字符串，通常也称为保留字。用户定义的标识符不应与关键字相同。Ｃ语言的关键字分为以下几类：<br>(1)类型说明符<br>用于定义、说明变量、函数或其它数据结构的类型。如int,double等<br>(2)语句定义符<br>用于表示一个语句的功能。如if else就是条件语句的语句定义符。<br>(3)预处理命令字<br>用于表示一个预处理命令。如include define。<br><br>3.运算符——Ｃ语言中含有相当丰富的运算符。运算符与变量，函数一起组成表达式，表示各种运算功能。运算符由一个或多个字符组成。<br><br>4.分隔符——在C语言中采用的分隔符有逗号和空格两种。逗号主要用在类型说明和函数参数表中，分隔各个变量。空格多用于语句各单词之间，作间隔符。在关键字，标识符之间必须要有一个以上的空格符作间隔， 否则将会出现语法错误，例如把int a;写成 inta;C编译器会把inta当成一个标识符处理，其结果必然出错。<br><br>5.常量——C语言中使用的常量可分为数字常量(const int)、字符常量(const char)、字符串常量(const string)、符号常量、转义字符(\n \t)等多种。<br><br>6.注释符——C语言的注释符是以&#8220;/*&#8221;开头并以&#8220;*/&#8221;结尾的串。在&#8220;/*&#8221;和&#8220;*/&#8221;之间的即为注释。程序编译时，不对注释作任何处理。注释可出现在程序中的任何位置。注释用来向用户提示或解释程序的意义。在调试程序中对暂不使用的语句也可用注释符括起来，使翻译跳过不作处理，待调试结束后再去掉注释符。<br><br>在Ｃ语言中，数据类型可分为：基本数据类型，构造数据类型，指针类型，空类型四大类。<br>基本数据类型最主要的特点是，其值不可以再分解为其它类型。也就是说，基本数据类型是自我说明的。<br>构造数据类型是根据已定义的一个或多个数据类型用构造的方法来定义的。也就是说，一个构造类型的值可以分解成若干个&#8220;成员&#8221;或&#8220;元素&#8221;。每个&#8220;成员&#8221;都是一个基本数据类型或又是一个构造类型。在C语言中，构造类型有数组类型,结构类型,联合类型<br>指针类型指针是一种特殊的，同时又是具有重要作用的数据类型。其值用来表示某个量在内存储器中的地址。虽然指针变量的取值类似于整型量，但这是两个类型完全不同的量，因此不能混为一谈。<br>空类型在调用函数值时，通常应向调用者返回一个函数值。这个返回的函数值是具有一定的数据类型的，应在函数定义及函数说明中给以说明,但是，也有一类函数，调用后并不需要向调用者返回函数值， 这种函数可以定义为&#8220;空类型&#8221;。其类型说明符为void。<br>对于基本数据类型量，按其取值是否可改变又分为常量和变量两种。在程序执行过程中，其值不发生改变的量称为常量，取值可变的量称为变量。它们可与数据类型结合起来分类。例如，可分为整型常量、整型变量、浮点常量、浮点变量、字符常量、字符变量、枚举常量、枚举变量。在程序中，常量是可以不经说明而直接引用的，而变量则必须先说明后使用。<br>整型量包括整型常量、整型变量。整型常量就是整常数。在Ｃ语言中，使用的整常数有八进制、十六进制和十进制三种。<br>整型常量<br>1.八进制整常数八进制整常数必须以0开头，即以0作为八进制数的前缀。数码取值为0～7。八进制数通常是无符号数。<br>2.十六进制整常数的前缀为0X或0x。其数码取值为0~9，A~F或a~f。<br>整型变量<br>1.基本型:类型说明符为int，在内存中占2个字节，其取值为基本整常数。<br>2.短整量:类型说明符为short int或short'C110F1???。所占字节和取值范围均与基本型相同。<br>3.长整型:类型说明符为long int或long ，在内存中占4个字节，其取值为长整常数。<br>4.无符号型:类型说明符为unsigned。无符号型又可与上述三种类型匹配而构成：<br>(1)无符号基本型 类型说明符为unsigned int或unsigned。<br>(2)无符号短整型 类型说明符为unsigned short<br>(3)无符号长整型 类型说明符为unsigned long <br>各种无符号类型量所占的内存空间字节数与相应的有符号类型量相同。但由于省去了符号位，故不能表示负数。<br>整型变量的说明:变量说明的一般形式为： 类型说明符 变量名标识符，变量名标识符，...; <br><br>类型说明符　　　　&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;数的范围 　　　　&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;分配字节数<br>int 　　　　　　&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;-32768~32767 　　　　&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; ■■ <br>short int 　　　&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;-32768~32767 　　　　&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; ■■<br>signed int 　　 &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;-32768~32767 　　　　&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; ■■<br>unsigned int 　 &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; 0~65535 　　　　　&nbsp; ■■<br>long int 　&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; -2147483648~2147483647　　&nbsp;&nbsp; &nbsp;&nbsp; ■■■■<br>unsigned long 　&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; 0~4294967295 　　　■■■■<br><br>在书写变量说明时，应注意以下几点：<br>1.允许在一个类型说明符后，说明多个相同类型的变量。各变量名之间用逗号间隔。类型说明符与变量名之间至少用一个空格间隔。<br>2.最后一个变量名之后必须以分号(;)号结尾。<br>3.变量说明必须放在变量使用之前。一般放在函数体的开头部分。<br><br>实型量<br>实型常量:实型也称为浮点型。实型常量也称为实数或者浮点数。在Ｃ语言中，实数只采用十进制。它有二种形式:十进制数形式,指数形式<br>1.十进制数形式<br>由数码0~ 9和小数点组成<br>2.指数形式<br>由十进制数，加阶码标志&#8220;e&#8221;或&#8220;E&#8221;以及阶码（只能为整数，可以带符号）组成。其一般形式为a E n （a为十进制数，n为十进制整数）其值为 a*10,n　<br>标准Ｃ允许浮点数使用后缀。后缀为&#8220;f&#8221;或&#8220;F&#8221;即表示该数为浮点数。<br><br>实型变量<br>实型变量分为两类：单精度型和双精度型，<br>其类型说明符为float 单精度说明符，double 双精度说明符。在Turbo C中单精度型占4个字节（32位）内存空间，其数值范围为3.4E-38～3.4E+38，只能提供七位有效数字。双精度型占8 个字节（64位）内存空间，其数值范围为1.7E-308～1.7E+308，可提供16位有效数字。<br>实型变量说明的格式和书写规则与整型相同。<br><br>字符型量<br>包括字符常量和字符变量。<br>字符常量是用单引号括起来的一个字符。例如'a','b','=','+','?'都是合法字符常量。在Ｃ语言中，字符常量有以下特点： <br>1.字符常量只能用单引号括起来，不能用双引号或其它括号。<br>2.字符常量只能是单个字符，不能是字符串。<br>3.字符可以是字符集中任意字符。但数字被定义为字符型之后就<br>不能参与数值运算。如'5'和5 是不同的。'5'是字符常量，不能参与运算。<br><br>转义字符<br>一种特殊的字符常量。转义字符以反斜线"\"开头，后跟一个或几个字符。转义字符具有特定的含义，不同于字符原有的意义，故称&#8220;转义&#8221;字符。例如，在前面各例题printf函数的格式串中用到的&#8220;\n&#8221;就是一个转义字符，其意义是&#8220;回车换行&#8221;。转义字符主要用来表示那些用一般字符不便于表示的控制代码。<br>常用的转义字符及其含义<br>转义字符 　转义字符的意义<br>\n 　　　　　回车换行<br>\t 　　　　　横向跳到下一制表位置<br>\v 　　　　　竖向跳格<br>\b 　　　　　退格<br>\r 　　　　　回车<br>\f　　　　 　走纸换页<br>\\ 　　　　　反斜线符"\"<br>\' 　　　　　单引号符<br>\a 　　　　　鸣铃<br>\ddd 　　　　1～3位八进制数所代表的字符<br>\xhh 　　　　1～2位十六进制数所代表的字符<br>广义地讲，Ｃ语言字符集中的任何一个字符均可用转义字符来表示。表2.2中的\ddd和\xhh正是为此而提出的。ddd和hh分别为八进制和十六进制的ASCII代码。如\101表示字母"A" ，\102表示字母"B"，\134表示反斜线，\XOA表示换行等。<br><br>字符串常量是由一对双引号括起的字符序列。<br>字符串常量和字符常量是不同的量。它们之间主要有以下区别：<br>1.字符常量由单引号括起来，字符串常量由双引号括起来。<br>2.字符常量只能是单个字符，字符串常量则可以含一个或多个字符。<br>3.可以把一个字符常量赋予一个字符变量，但不能把一个字符串常量赋予一个字符变量。在Ｃ语言中没有相应的字符串变量。<br>这是与BASIC 语言不同的。但是可以用一个字符数组来存放一个字符串常量。在数组一章内予以介绍。<br>4.字符常量占一个字节的内存空间。字符串常量占的内存字节数等于字符串中字节数加1。增加的一个字节中存放字符"\0"(ASCII码为0)。这是字符串结束的标志。例如，字符串 "C program"在内存中所占的字节为：C program\0。字符常量'a'和字符串常量"a"虽然都只有一个字符，但在内存中的情况是不同的。 <br>'a'在内存中占一个字节，可表示为：a<br>"a"在内存中占二个字节，可表示为：a\0符号常量<br><br>自动转换 <br>自动转换发生在不同数据类型的量混合运算时，由编译系统自动完成。自动转换遵循以下规则： <br>1.若参与运算量的类型不同，则先转换成同一类型，然后进行运算。<br>2.转换按数据长度增加的方向进行，以保证精度不降低。如int型和long型运算时，先把int量转成long型后再进行运算。<br>3.所有的浮点运算都是以双精度进行的，即使仅含float单精度量运算的表达式，也要先转换成double型，再作运算。<br>4.char型和short型参与运算时，必须先转换成int型。<br>5.在赋值运算中，赋值号两边量的数据类型不同时， 赋值号右边量的类型将转换为左边量的类型。 如果右边量的数据类型长度左边长时，将丢失一部分数据，这样会降低精度， 丢失的部分按四舍五入向前舍入。<br>强制类型转换<br>强制类型转换是通过类型转换运算来实现的。其一般形式为： (类型说明符) (表达式) 其功能是把表达式的运算结果强制转换成类型说明符所表示的类型。例如： (float) a 把a转换为实型，(int)(x+y) 把x+y的结果转换为整型在使用强制转换时应注意以下问题：<br>1.类型说明符和表达式都必须加括号(单个变量可以不加括号)，如把(int)(x+y)写成(int)x+y则成了把x转换成int型之后再与y相加了。<br>2.无论是强制转换或是自动转换，都只是为了本次运算的需要而对变量的数据长度进行的临时性转换，而不改变数据说明时对该变量定义的类型。<br><br>运算符的种类Ｃ语言的运算符可分为以下几类：<br>1.算术运算符<br>用于各类数值运算。包括加(+)、减(-)、乘(*)、除(/)、求余(或称模运算，%)、自增(++)、自减(--)共七种。<br>2.关系运算符<br>用于比较运算。包括大于(&gt;)、小于(&lt;)、等于(==)、 大于等于(&gt;=)、小于等于(&lt;=)和不等于(!=)六种。<br>3.逻辑运算符<br>用于逻辑运算。包括与(&amp;&amp;)、或(||)、非(!)三种。<br>4.位操作运算符<br>参与运算的量，按二进制位进行运算。包括位与(&amp;)、位或(|)、位非(~)、位异或(^)、左移(&lt;&lt;)、右移(&gt;&gt;)六种。<br>5.赋值运算符<br>用于赋值运算，分为简单赋值(=)、复合算术赋值(+=,-=,*=,/=,%=)和复合位运算赋值(&amp;=,|=,^=,&gt;&gt;=,&lt;&lt;=)三类共十一种。<br>6.条件运算符<br>这是一个三目运算符，用于条件求值(?:)。<br>7.逗号运算符<br>用于把若干表达式组合成一个表达式(，)。<br>8.指针运算符<br>用于取内容(*)和取地址(&amp;)二种运算。<br>9.求字节数运算符<br>用于计算数据类型所占的字节数(sizeof)。<br>10.特殊运算符<br>有括号()，下标[]，成员(&#8594;，.)等几种。<br><br>在使用switch语句时还应注意以下几点：<br>1.在case后的各常量表达式的值不能相同，否则会出现错误。<br>2.在case后，允许有多个语句，可以不用{}括起来。<br>3.各case和default子句的先后顺序可以变动，而不会影响程序执行结果。<br>4.default子句可以省略不用。
<br><img src ="http://www.cppblog.com/paladino/aggbug/26548.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/paladino/" target="_blank">Gu.paladino</a> 2007-06-18 10:13 <a href="http://www.cppblog.com/paladino/archive/2007/06/18/26548.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>复习的准备：第一步&lt;book_List&gt;</title><link>http://www.cppblog.com/paladino/archive/2007/06/06/25656.html</link><dc:creator>Gu.paladino</dc:creator><author>Gu.paladino</author><pubDate>Wed, 06 Jun 2007 07:48:00 GMT</pubDate><guid>http://www.cppblog.com/paladino/archive/2007/06/06/25656.html</guid><wfw:comment>http://www.cppblog.com/paladino/comments/25656.html</wfw:comment><comments>http://www.cppblog.com/paladino/archive/2007/06/06/25656.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/paladino/comments/commentRss/25656.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/paladino/services/trackbacks/25656.html</trackback:ping><description><![CDATA[准备了复习C++要看的书的list，其实学习的任务主要就是读书。<br>查阅了很多blog，看了一些大牛们的书评和他们的学习旅程，我觉得我走上了学习计算机科学和数学科学的正确道路上，家里有的书，电子书多的就不得了了，呵呵，积攒了很多年的东东，其实想学习任何东西都可以在网络上找到资料的，呵呵，就看你会不会用google了。<br>中文的：<br>《C++入门经典》<br>《C++高级编程》<br>《Thinking in C++,vol1,vol2》<br>英文的：<br>《The C++ program language》<br>《Effective C++》<br>《More Effective C++》<br>电子的：<br>aha，so many，that&#8217;s so good!<br><br>找到了Hello world的很多种写法，有几种没看明白，呵呵。<br>1. 最经典的&#8220;Hello world!&#8221;<br>&#8220;Hello world!&#8221;最经典的写法当然是直接用 printf 输出&#8220;Hello world!&#8221;这几个字符了。无论用C还是 C++，写起来都非常的简洁明了。这里把最常见的几个全部列在下面。<br>#include &lt;stdio.h&gt;<br>#include &lt;iostream&gt;<br>int main()<br>{<br>&nbsp;&nbsp;&nbsp; printf("Hello world!");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 教科书的写法<br>&nbsp;&nbsp;&nbsp; puts("Hello world!");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 我最喜欢的<br>&nbsp;&nbsp;&nbsp; puts("Hello" " " "world!");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 拼接字符串<br>&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; "Hello world!" &lt;&lt; std::endl; // C++风格的教科书写法<br>&nbsp;&nbsp;&nbsp; return 0;<br>}<br>特别需要注意的是，在C/C++里，如果两个字符串之间除空白符以外没有任何东西，编译器会自动认为这两个字符串是连在一起的字符串。这样，如果一个字符串过长，可以用这种方法换行来写，既不浪费性能，又美观。<br><br>2. 用宏写的&#8220;Hello world!&#8221;<br>在C/C++里，宏是一个神奇的东西。特别是在C语言中，宏可以帮我们做一些&#8220;又脏又累&#8221;的活，包括拼接代码片断、隐藏繁琐的实现细节等等。其中特别有趣的是&#8220;#&#8221;的用法，它可以&#8220;提取&#8221;参数的名字，把它变成字符串。<br>#include &lt;stdio.h&gt;<br>#define Say(sth) puts(#sth)<br>int main()<br>{<br>&nbsp;&nbsp;&nbsp; return Say(Hello world!);<br>}<br>请注意，这个Hello world可是完全没有出现引号哦！<br><br>3. 断章取义的&#8220;Hello world!&#8221;<br>字符串是一种常量这当然毫无疑问，但是它的类型是什么，这就需要考虑一下了。使用C++的typeid就可以这个问题的答案，而且只要是符合C或C++标准的编译器就应该是一样的结果。比如字符串&#8220;Hello world!&#8221;，它的类型就是 char const [13]。<br>知道了这个，就可以写出以下的&#8220;Hello world!&#8221;：<br>#include &lt;stdio.h&gt;<br>int main()<br>{<br>&nbsp;&nbsp;&nbsp; return puts(&amp;"Do not say: Hello world!"[12]);<br>}<br><br>4. 退出时运行的&#8220;Hello world!&#8221;<br>大家都知道 main 函数退出意味着程序结束，可是这并不完全正确，我们完全可以在 main 函数退出以后做很多事呢——比如说，输出 &#8220;Hello world!&#8221;。这个功能依赖于C标准库中提供的函数 atexit()，调用这个函数并注册自己的回调函数就行。需要注意，这个函数可以调用多次，最后注册的函数最先执行。<br>#include &lt;stdio.h&gt;<br>#include &lt;stdlib.h&gt;<br>void say()<br>{<br>&nbsp;&nbsp;&nbsp; printf("world!");<br>}<br>void sth()<br>{<br>&nbsp;&nbsp;&nbsp; printf("Hello ");<br>}<br>int main()<br>{<br>&nbsp;&nbsp;&nbsp; return atexit(say), atexit(sth);<br>}<br><br>5. 读取自己的&#8220;Hello world!&#8221;<br>C/C++的编译器提供了一些有用的内置宏，最常用的就是 __FILE__ 和 __LINE__ 了。其中，__FILE__ 代表当前的源文件的文件名，嗯，对了，如果我们让这个程序读取自己的源文件，不就可以做一个很有意思的&#8220;Hello world!&#8221;了么？<br>// Hello world!<br>#include &lt;iostream&gt;<br>#include &lt;fstream&gt;<br>#include &lt;string&gt;<br>int main()<br>{<br>&nbsp;&nbsp;&nbsp; std::ifstream ifs(__FILE__);<br>&nbsp;&nbsp;&nbsp; std::string say, some, word;<br>&nbsp;&nbsp;&nbsp; ifs &gt;&gt; say &gt;&gt; some &gt;&gt; word;<br>&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; some &lt;&lt; " " &lt;&lt; word;<br>&nbsp;&nbsp;&nbsp; return 0;<br>}<br><br>6. 话分两头的&#8220;Hello world!&#8221;<br>有了C++的类，我们就可以光明正大的在 main 函数执行之前和之后做感兴趣的事情了。我们可以声明一个全局的类的实例，这样，在 main 函数执行之前会调用这个类的构造函数，结束之后则会调用析构函数。<br>#include &lt;iostream&gt;<br>class say<br>{<br>public:<br>&nbsp;&nbsp;&nbsp; say()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; "Hell";<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; ~say()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; "world!";<br>&nbsp;&nbsp;&nbsp; }<br>}hello;<br>int main()<br>{<br>&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; "o ";<br>&nbsp;&nbsp;&nbsp; return 0;<br>}<br><br>7. 传入模板的&#8220;Hello world!&#8221;<br>C++的模板功能极为强大，可以说是C++里面最艰深、最经典、最时尚的部分。一个&#8220;Hello world!&#8221;当然无法使用很多很高级的模板技巧，我也不想只使用模板特化这样无阻挂齿的小技巧，嗯，那就来演示一个比较罕见的用法吧。<br>#include &lt;iostream&gt;<br>template &lt;char * words&gt;<br>class say<br>{<br>public:<br>&nbsp;&nbsp;&nbsp; void operator () ()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; words;<br>&nbsp;&nbsp;&nbsp; }<br>};<br>extern char hello[] = "Hello world!";<br>int main()<br>{<br>&nbsp;&nbsp;&nbsp; return say&lt;hello&gt;()(), 0;<br>}<br>请注意，这个 extern 是十分必要的，只有加上了 extern，这个指针才是一个编译器间可以确定的值，也才可以参与模板运算。还有，hello 必须为数组类型，而不能为 char*，这个道理和加 extern 是一样的。<br>此外，这里还演示了 functor 的用法，嗯，关于它的优点就不在这里多说了，反正是与原生指针相比有很多好处就是了。<br><br>8. 调用私有函数的&#8220;Hello world!&#8221;<br>我们知道，C++类的私有函数是不能被外界访问的，比如说 main 函数里面，它绝对不能访问类的私有函数，除非把它设为类的友元函数。不过我们还是可以用一些比较奇怪的方法访问类的私有函数——当然，这个私有函数必须满足一个条件：它是虚函数。<br>这里就涉及到一个问题，指向虚函数的虚表放在哪里？对于 VS.Net 2003 而言，虚表是类的第一个成员，虚函数指针按照函数声明的顺序放在虚表里面。当然，这个说法并不严谨，更细节的东西还是去看看那本&#8220;成人高钙奶粉&#8221;吧，它会给出最权威的解答。<br>这里是一个很有意思的例子：<br>#include &lt;iostream&gt;<br>#include &lt;cstddef&gt;<br>class secret<br>{<br>private:<br>&nbsp;&nbsp;&nbsp; virtual void say()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; "Hello world!";<br>&nbsp;&nbsp;&nbsp; }<br>};<br>int main()<br>{<br>&nbsp;&nbsp;&nbsp; secret word;<br>&nbsp;&nbsp;&nbsp; (reinterpret_cast&lt;void (*)()&gt;(**(intptr_t**)(&amp;word)))();<br>&nbsp;&nbsp;&nbsp; return 0;<br>}<br><br>9. 最暴力的&#8220;Hello world!&#8221;<br>最暴力的调用函数的方法是：直接修改函数的返回地址，让这个地址指向我们想要调用的函数。这也就是缓冲区溢出漏洞的应用方法了，不过里面还涉及到很多问题，在这里就不一一列举，想要了解的话，还是去 Google 吧。这里只演示一个可以在 VS.Net 2003 下可以用的 &#8220;Hello world!&#8221;。<br>#include &lt;stdio.h&gt;<br>#include &lt;stdlib.h&gt;<br>#include &lt;stddef.h&gt;<br>void say()<br>{<br>&nbsp;&nbsp;&nbsp; puts("Hello world!");<br>&nbsp;&nbsp;&nbsp; exit(0);<br>}<br>int main()<br>{<br>&nbsp;&nbsp;&nbsp; volatile intptr_t a = 0;<br>&nbsp;&nbsp;&nbsp; volatile intptr_t * p = &amp;a;<br>&nbsp;&nbsp;&nbsp; *(p + 2) = (intptr_t)say;<br>&nbsp;&nbsp;&nbsp; *(p + 3) = (intptr_t)say;<br>&nbsp;&nbsp;&nbsp; return 0;<br>}<br><br>10. 外星人说的&#8220;Hello world!&#8221;<br>好了，这个&#8220;Hello world!&#8221;是最匪夷所思的一个了！不过它并没有涉及任何复杂的C/C++语言特性，只是看起来有点酷。你能看懂外星人在说什么不？<br>#include &lt;stdio.h&gt;<br>void alien_say(char * p)<br>{<br>&nbsp;&nbsp;&nbsp; while (putchar(*(p += *(p + 1) - *p)));<br>}<br>int main()<br>{<br>&nbsp;&nbsp;&nbsp; return alien_say("BETHO! Altec oh liryom(a loadjudas!) dowd."), 0;<br>}<br><img src ="http://www.cppblog.com/paladino/aggbug/25656.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/paladino/" target="_blank">Gu.paladino</a> 2007-06-06 15:48 <a href="http://www.cppblog.com/paladino/archive/2007/06/06/25656.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>必不可少的 “hello world”</title><link>http://www.cppblog.com/paladino/archive/2007/06/05/25583.html</link><dc:creator>Gu.paladino</dc:creator><author>Gu.paladino</author><pubDate>Tue, 05 Jun 2007 10:13:00 GMT</pubDate><guid>http://www.cppblog.com/paladino/archive/2007/06/05/25583.html</guid><wfw:comment>http://www.cppblog.com/paladino/comments/25583.html</wfw:comment><comments>http://www.cppblog.com/paladino/archive/2007/06/05/25583.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/paladino/comments/commentRss/25583.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/paladino/services/trackbacks/25583.html</trackback:ping><description><![CDATA[学习任何一种语言都是从最最简单的hello world开始的，呵呵，复习也不例外，每次复习hello world也能有很多收获，可以写成很多很多的方式，C++就是这么灵活啊，下次写写，查查，统计一下，好像有人写过10中，不过我估计不止，呵呵。<br>#include &lt;iostream&gt;<br>int main()<br>{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; "Hello world!" &lt;&lt; std::endl; <br>&nbsp;&nbsp;&nbsp; return 0;<br>}<br>这个就是最经典的吧？<img src ="http://www.cppblog.com/paladino/aggbug/25583.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/paladino/" target="_blank">Gu.paladino</a> 2007-06-05 18:13 <a href="http://www.cppblog.com/paladino/archive/2007/06/05/25583.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>