最新 C语言计算机.docx
- 文档编号:4344915
- 上传时间:2022-11-30
- 格式:DOCX
- 页数:21
- 大小:40.62KB
最新 C语言计算机.docx
《最新 C语言计算机.docx》由会员分享,可在线阅读,更多相关《最新 C语言计算机.docx(21页珍藏版)》请在冰豆网上搜索。
最新C语言计算机
C语言
★在1973年,美国贝尔实验室的D.M.Ritchie(丹尼斯·里奇)在B语言的基础上最终设计出了一种新的语言,他取了BCPL的第二个字母作为这种语言的名字,这就是C语言,并首次用C重新实现了UNIX操作系统。
★1978年BrianW.Kernighan和DennisM.Ritchie出版的名著《C程序设计语言(TheCProgrammingLanguage)》,常被人们称为K&R版C教材或“白皮书”,为C语言的推广普及立下汗马功劳。
在书籍方面我还要极力推荐的一本精典著作就是《C和指针》,写的特别深入、详细。
1、C语言是一门兼具高级语言功能和低级语言大部分功能的程序开发语言,所以既能开发应用软件也能开发系统软件。
2、C程序是由函数构成的,一个C源程序至少且仅包含一个main函数。
一个C程序总是从main函数开始执行的,而不论main函数在整个程序的位置如何。
main(intargc,char*c[])主函数也可以带参数,此时在命令行执行test.exemawentao,那么总共有三个参数,argc就等于3,c[0]是源程序名"test.exe",c[1]是ma,c[2]是wen,c[3]是tao。
3、C语言是严格区分大、小写的,比如定义变量时:
inta和intA是两个完全不同的变量。
4、C语言中整常数可以有3种表示形式:
(1)默认为十进制。
(2)以0开头为八进制,如:
0123表示八进制123,十进制为83。
(3)以0x开头为十六进制(没有直接表示二进制格式,所以可以用十六进制表示),如:
0x123。
5、数据类型的长度由编译器决定,比如TurboC给int型变量分配2个字节的存储单元,而VisualC++6.0则分配4字节。
★这里简单说下C语言变量在内存中的存储位置:
(1)全局变量和静态变量都在静态内存区,说白了也就是普通内存区即进程所分配的地址空间,当程序退出自动释放。
(2)函数的参数和局部变量都在堆栈中,函数退出后这些变量都会自动出栈,即释放内存。
(3)用malloc、calloc、realloc分配的内存属于堆区,必须手动调用free函数释放,否则会造成内存泄露。
(4)寄存器变量,直接存储在寄存器中,存取值速度快,只有局部自动(非静态)变量和形式参数可以这样定义。
如:
register...
6、整数默认就是有符号数,浮点型常量默认为双精度,有些编译器比如TurboC把字符型变量默认定义为signedchar型,即有符号字符,这样它的范围就是-128到127之间了,但有些编译器默认字符是无符号(unsignedchar)的,范围在0到255之间。
7、%模运算符(求余数)两侧均应为整型数据。
8、变量使用前必须先声明,而且声明要在代码之前(即变量声明紧随代码块左大括号)。
9、关系运算符(<,>,<=,>=,==,!
=)的判断结果有真,假两个值,真值用非0表示,假用0表示,没有true和false等关键字。
C语言的逻辑运算符(&&,||,!
)与、或、非的判断结果是假则值为0,结果为真则值为非0(包括任何非0数)。
10、逻辑表达式在求解中,并不是所有的逻辑运算符都被执行,只是在必须执行下一个逻辑运算符后才能确定表达式结果时才执行后面运算,比如:
a&&b&&c如果a为真(非0)才去计算b,如果a为假(0)则b和c都不会去执行,最终结果就是假。
11、if语言的判断条件是一个关系表达式或逻辑表达式,由于逻辑表达式的真用非0代表,所以if语句的判断条件可以是0和任意非0数值,包括(整数、实型、字符型、指针型),如:
if(3) printf("0k");或者if('a')printf("no");都是合法的。
切记即使在条件判断和循环判断中传的是负数也会为真,即if(-2)...while(-1)等等这样的表达式都会为真,只要不是0就为真。
12、条件表达式即三目运算符x?
a:
b中a和b的结果类型不同,则三目运算符的最终结果会取类型较高的,比如x>y?
1:
1.5,如果x>y为真则最终结果为1.0。
13、for循环中for(表达式1;表达式2;表达式3),都可以省略这样就成了死循环,但分号不能去掉。
而且表达式1和表达式3中都可以包括多个表达式用逗号分隔如,比如:
for(i=1,j=2;i<100;i++,j++)。
14、while循环、do...while循环和for循环可以用break语句跳出循环,用continue语句结束本次循环,但对于goto语句和if语句构成的循环不能用break和continue进行控制。
切记:
do....while();这里while()括号后面的分号不能省略。
break的作用只有两个:
(1)跳出最近的那层循环。
(2)跳出最近的整个switch语句。
15、提到字符串就必须说说字符串常量,比如:
char*c="asdf";这样用指针定义的字符串常量不能改变字符串的任何字符,因为字符串常量存储在静态内存区的只读区域,所以如果你试图用*c++='m'等语句想改变字符串的内容,系统编译不会发现问题,但运行时则会报错,这个问题前期一般很难发现,所以必须谨慎,字符数组可以修改如:
chara[]="sdf",(奇怪的是好多C程序书籍居然没有提到这一点,真不明白现在的作者都是以何目的而写作的)。
还有一点就是字符串连接:
"ma""wentao"就等价于"mawentao"
16、关于数组要说的首先是数组名,数组名在作为&和sizeof的操作数时,不会当做指针用,此时就代表整个数组,即chara[]="bao";&a就是数组的起始地址,即&a[0].
其次,函数不能返回数组,只能返回数组的首地址(指针),关于数组的初始化必须按顺序来。
最后,数组中的元素长度都是相同的,即都是相同的类型,所以数组元素不可能是像函数等等这些没固定长度的元素,而且定义数组时下标必须是个常量即数组大小在编译时就要确定。
(ANSI标准规定数组下标访问不能超过数组左边界,但VC++6.0没这限制,不论数组左边界还是右边界都可以随便超出访问,不过没实际意义,所以程序员自己要注意)
17、关于指针,好多作者都会给读者一个下马威,说是指针特别复杂,其实真没有什么,指针就是地址。
一般指针变量自身都占4个字节,它所指向的类型除了基本类型外比较复杂的有结构体、数组、函数。
数组名作为参数传递时就是首地址的拷贝,而结构仍是结构本身的拷贝。
指针复杂声明:
int**p;指针的指针。
float(*p)[4];数组指针。
int(*p)(int);函数指针。
array[5]等价于5[array],因为内部都是指针加下标偏移量实现的。
(复杂声明的理解技巧其实很简单,就是每次都从变量名开始根据它前后的符号确定其根本)
18、extern声明外部变量,可以扩展外部变量的作用域。
如:
externa,b;...inta=10,b=11;虽然a和b在extern语句之后定义但在extern后面且在a和b定义之前的语句都可以用a和b。
extern用于函数定义表示全局可见(不加也可以),用于变量说明它在其他地方定义。
19、在编译时,对类型是不分配空间的,只对变量分配空间。
比如:
建立结构体类型structstudent{charname[],intage};此时不会分配内存,只有定义了变量在系统编译时才分配空间。
比如:
structstudentstudent1;
20、sizeof操作符可以获得一个类型所占的字节数,sizeof不是个函数,如果后面的操作数不是个类型名就不用加括号。
如:
inti;sizeofi;当sizeof操作结构时,好多时候都大于结构中所有成员的长度和,这是由于字节对齐所造成的。
操作数组时会返回整个数组的长度。
21、typedef声明新的类型名来代替已有的类型名。
比如:
typedefintINTEGER
★typedef和define的主要区别两个:
(1)可以用其他类型说明符对宏类型名进行扩展,但对typedef所定义的类型名却不能这么做。
(2)在连续的几个变量声明中,用typedef定义的类型能够保证声明中的所有变量均为同一种类型,而用define定义的类型则无法保证。
比如连续定义指针类型时,define就会出问题。
22、>>右移操作符:
TurboC和其他一些编译器采用的是算数右移,即对有符号数右移时,如果原来符号位原来为1,左面移入高位的是1。
如果某个编译器对于右移采用逻辑右移则永远在高位补0,所以右移负数时存在不可移植性问题。
23、位段:
C语言中允许在一个结构体中以位为单位制定其成员所占内存长度,这种以位为单位的成员称为“位段”或称“位域”
利用位段能够用较少的位数存储数据。
(前提也是在结构体内,并且类型只能是int、unsignedint、singnedint)
例如:
structdata
{
unsigneda:
8;
unsignedb:
2;
unsignedc:
6;
}da;这样定义的结构体a、b、c分别占8位、2位、6位。
24、所有非整形函数一定要在调用之前声明。
(没有被声明就调用的函数被默认为返回整型)
(1)函数前面不写返回值默认就返回整型,但函数体此时可以不返回任何东西,也可以返回整数。
(2)函数不返回任何东西,可以显示的用void声明,比如这样定义主函数voidmain(){}。
(3)函数如果没有参数,可以用void显示说明,即voidremove(void){}
25、字符常数是int型,因此sizeof('a')是sizeof(int)即值为4,而不是1。
26、关键字const并不能把变量变成常量,在一个符号前加上const限定符只是表示这个符号不能被赋值,可以初始化一次。
注意:
constint*p;和intconst*p;都叫常量指针(这种读法很简单,因为先是const再是*),都是指针所指的对象不能修改。
int*constp;这和字符串常量、数组名(当做指针时)一样都叫指针常量,表示指针本身是不可变的。
constint*constp;和intconst*constp;表示指针和所指对象都是只读的。
27、void*v类型参数是一个通用的指针类型,即这种类型的指针可以转换成任意具体类型的指针,但它不可以移动,比如:
v++,v-1等等,这是因为此指针所指向的对象大小无法确定,那么它自然就不知道+1是移动多少了。
(这个解释实在太经典了,嘿嘿)
28、C语言在定义数组时,需要指定数组中元素的个数,方括号中的表达式用来表示元素的个数,即数组长度。
下标只能是表达式常量和符号常量,不能包含变量,也就是说C语言不允许对数组大小作动态定义,即数组的大小不依赖于程序运行过程中的变量值。
例如:
inta=10;ints[a];这样是错误的。
●C语言在编译时就要确定任何变量的存储空间大小,包括数组。
(可以想想汇编数据段中的内存分配)
29、"0123456789"[n%10]这个表达式将返回n(整数)的最后一位数值,别忘了字符串常量就是一个指针常量。
(为了防止字符表中的数字没有顺序排列)
30、对于参数的计算顺序和整形数右移是否扩展符号位,标准都没有规定,只能依赖编译器了。
31、C语言中两个字符串常量会自动合并。
比如chara[]="ma""wentao";等价于chara[]="mawentao";
32、有好多人经常问标准库函数到底是在哪里实现的?
为什么我们很简单的用include
33、C语言把文件看做一个字符(字节)序列,即C文件是一个字节流或二进制流,根据数据的组织形式不同,可以分为ascii文件和二进制文件ascii文件也叫文本文件,它的每一个字节存放一个ascii代码,代表一个字符。
二进制文件是把内存中的数据按其在内存中的存储形式原样输出到文件磁盘上存放。
注意文本/二进制文件区别只是发生在文件打开时,一旦文件打开之后,在其上调用什么I/O函数无关紧要。
用fopen打开文件时,路径有两种写法:
双反斜杠//、单正斜杠/。
34、有些专家建议在C语言的操作符中牢记两个优先级就够了:
乘法和除法优先于加法和减法,在涉及到其他操作符时,一律加上括号。
虽然有点夸张了,但我觉得我们真不应该把时间浪费在死记操作符的优先级上,而且为了代码的可读性和维护性就应该多加括号。
35、i=*x/*y;这里本意是指针x所指向的内容除以指针y所指向的内容然后赋给i,但/*被理解为注释开始了,编译器会报错,所以/和*之间必须加上空格。
这也是空格作用体现的一个很好例子,因此我们在写代码时一定要养成一个好的习惯,操作符两边都以空格分隔。
37、函数内部不能返回一个局部数组指针,如int*f(){inta[3]={1,2,4};returna;},这样返回了一个指针a,但函数结束后整个数组都被释放,a指向的内存内容是个未知的,或许已经被别的内容覆盖,这是很危险的。
38、声明只确定了变量的基本类型以及初始值(如果有的话).
39、如何解析C语言声明?
1、取最左边的标示符(变量名)
2、查看标示符右边的下一个符号,如果是方括号对于每一对方括号表示“...的数组”;如果是一个左括号,到右括号为止的内容表示“返回...的函数”;(如果变量名临近右边无任何有价值的符号就直接走第3步,比如int(*p)[2])
3、接着查看的左边符号,如果是一个左括号,这个左括号把已经处理的部分声明组合在一起,直到遇见对应的右括号,然后从第2步从新开始;
4、上面三部分析完后,在看已经处理的部分左边的符号如果是下述之一:
const、volatile、*,则继续向左边读符号,直到所读符号不再是上面那三个之一。
如果符号是const,表示“只读”;如果是volatile表示"volatile";如果是*,表示“指向...的指针”然后重复第三步;
5、剩下的符号形成声明的基本类型,剩下的所有符号可以一并阅读,如:
staticunsignedint。
切记:
const或volatile关键字后面如果紧跟类型说明符如(int、long),则它作用于类型说明符,其他情况下都作用于左边的临近指针星号。
举例比如:
char*const*(*next)();我们来简单分析下这个声明,就按照上面的5个步骤进行:
1、取最左边的标示符:
next,表示变量next是个...;
2和3都不匹配;
4、next左边是*,表示“next是指向...的指针”;再重复第三步,匹配到了一对小括号后再从第二步开始,表示“返回...的函数”;接着又到第三步:
不匹配,再去第四步:
左边遇到一个*即(*next)外面紧跟const的那个*,表示“指向...的指针”,因为右边我们已经分析完了就不再看前三步了,继续第四步遇到了const,“表示只读”;再又是一个“指向...的指针”,最后就是char类型定义了。
●上面所有合起来就是next是一个指向函数的指针,该函数返回另一个指针,该指针指向一个只读的指向char的指针。
再举例:
char*(*c[10])(int**p)就表示:
c是一个指针数组,即里面的元素全是指针,每个指针都指向一个函数,即函数指针,该函数有个指向int型指针的指针的参数,返回值是个char型指针。
●注意:
在数组中被函数指针指向的所有函数都把一个指向指针的指针作为它们的唯一参数。
(上面就是一个例子)
40、关于补码请记住:
对于有符号数,正数和负数都是由补码构成的。
(汇编语言)
一个正数的补码取反加1后,为其负数的补码;负数的补码取反加1后,为其绝对值。
41、D:
\soft\vc++6.0\VC6CN\VC98\INCLUDE,这是VC++6.0中头文件所存放的目录。
(我的VC装在D盘的soft下)
用<>括起来的头文件一般先会在标准位置搜索即上面的目录,用“”括起来的头文件首先会在当前目录搜索,然后去标准位置搜索。
42、switch(此处必须是个整型){
case1:
......;break;
case2:
......;break;
default:
.....;break;此处break可加,也可不加,不过加了以后维护方便些。
}
43、判断偶数的小技巧就是看二进制最后一位是否为0,如果是0则为偶数,为1就是奇数。
44、可变参数列表的应用主靠头文件
(具体应用任何C书籍都有提到)
45、structstudent1{
chara;
intb;
charc;
}s1;
由于字节对齐要求声明上面结构体比较浪费内存(比如在32位机器上,s1会浪费6个字节,因为CPU从内存获取数据时是从地址空间为4的整数倍开始取的,则CPU下个周期会移动4byte取数据)
所以可以这样声明:
structstudent2{
intb;
chara;
charc;
}s2;
而且这里结构体变量名s2和数组名不同,s2不会当做一个指向结构体第一个成员的指针,s2就代表整个结构。
46、函数指针用法,intf(float);int(*p)(float)=&f;这里的&可加可不加(p=f),因为函数名在使用时本来就当做函数指针用的,接着函数可以这么调用:
inti; i=f(7.28); i=(*p)(7.28); i=p(7.28);
47、#define宏定义中:
#argument这种结构,可以把宏参数argument转换成字符串。
如果宏内容中出现两个#号,比如:
sum##i;##会把位于它两本的符号组合成一个标识符。
切记:
宏语句最好不要以分号结束。
(当宏内容太长了,可以换行并在除过最后一行的所有行末尾加上反斜杠)。
#undef用于移除一个宏定义,如果一个现存的名字需要被重新定义,那它的旧定义必须用#undef移除。
48、条件编译指令:
(1)#if constant-expression //这里#if后面的条件是个常量表达式,即字面值常量或者由#define定义的符号。
当其值为0则statements不会被编译,为非0时会正常编译。
statements
#elifconstant-expression //这里elif出现的次数不限,
otherstatements
#else
otherstatements
#endif
(2)#ifdefsymbol //如果定义了symbol,此条件编译指令和#ifdefined(symbol)是等价的,这里的defined也是个预处理指令。
#ifndefsymbol //如果没有定义symbol,此条件编译指令和#if!
defined(symbol)是一样的。
(3)#error //允许你生成错误指令
(4)#line //通知预处理器输入的行号
(5)#progma //支持因编译器不同的特性
49、为了防止#include指令包含多个相同的头文件,可以使用:
#ifndefHONG
#defineHONG1
......
#endif
50、流:
就C而言,所有的I/O操作只是简单的从程序移进或移出字节序列,这些字节序列就是字节流简称为流。
我们的程序只关心创建正确的输出字节数据,以及正确的解释从输入读取的字节数据。
特定I/O设备的I/O操作细节对程序员来说是隐藏的。
绝大多数流是完全缓冲的,这意味着“读取”和“写入”实际上是从一块被称为缓冲区的内存区域来回复制数据。
用于输出流的缓冲只有当它写满时才会被刷新(flush)到设备或文件中。
同样,输入缓冲区当它为空时通过从设备或文件读取下一块较大的输入,重新填充缓冲区。
●流分为:
文本流(文本文件、字符流)和二进制流(二进制文件、字节流),这两种流的划分都是由写入和读取时的打开方式决定的。
51、文本文件(文本流):
是以特定的编码方式写入I/O设备,并且要以特定的解码方式打开,否则这些信息将会变成乱码而无法解释。
52、二进制文件(二进制流):
二进制流中的字节将完全根据程序编写他们的形式写入到文件或设备中,而且完全根据他们从文件或设备读取的形式读入到程序中。
53、FILE是个结构,在
如果你同时激活几个流,每个流都有一个相应的FILE与它关联。
54、对于每个ANSIC程序,运行时系统必须至少提供三个流,标准输入(stdin)、标准输出(stdout)、标准错误(stderr),他们都是一个指向FILE结构的指针。
操作系统一般都允许程序员修改缺省的输入输出设备。
比如修,(键盘、屏幕)。
●I/O函数以三种基本形式处理数据:
单个字符(getchar和putchar家族)、文本行(gets和puts家族、scanf和printf家族)和二进制数据(fread和fwrite家族)。
对于每种形式,都有一组特定的函数对他们进行处理。
55、打开流的常用模式:
读取 写入 可读可写(用于更新) 可读可写(有就删除) 添加(有不会删除) 更新(可读可写)
文本:
"r" "w" "r+" "w+" "a" "a+"
二进制:
"r
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 最新 C语言计算机 语言 计算机