c语言学习文档

来源:互联网 发布:美的空调 知乎 编辑:程序博客网 时间:2024/04/28 17:54

第二章      基础数据类型与输入输出

1.  基本数据类型

一个程序要运行,就要先描述其算法。描述一个算法应先说明算法中要用的数据,数据以变量或常量的形式来描述。每个变量或常量都有数据类型。

   基本数据类型有char(字符型),int(整型),float(浮点型)和double(双精度型)。在不同的计算机上,每个变量类型所占用的内存空间的长度不一定相同。例如,在16位计算机中,整型变量占2个字节,而在32位计算机中,整型变量占4个字节。

     16位计算机的表示为例:

     Char unsigned charsigned char------------------------------------------1个字节

    

Intunsigned intsigned int

     Short int unsigned short intsigned short int---------------------------2个字节

    

     Long intfloat------------------------------------------------------------4个字节

 

     Double---------------------------------------------------------------------8个字节

 

Long double-----------------------------------------------------------------10个字节

          另外用sizeof(数据类型)可以确定某数据类型的字节长度。

2.  变量的定义

C++是大小写敏感的,即大写和小写认为是不同的字母。

typedef可以为一个已有的类型提供一个同义词。用法是,以typedef开始,随后是要表示的类型,最后是新的类型名和分号。但是,typedef没有实际的定义一个新的数据类型,在奖励一个typedef类型时没有分配内存空间。

3.  常量

整型常量,可以有3种表示方式:10进制整数,8进制整数(以0开头),16进制(以0x开头)。

实型常量,有两种表示:小数形式,指数形式(123e5 = 123×105)。

字符常量,使用单引号括起来的一个字符。在内存中,字符数据以ASCII码存储,即以整数表示,所以字符数据和整型数据之间可以相互赋值,只要注意其表示的范围合理。例:int a = b’char c = 97

字符串常量,是由一对双括号扣起来的字符序列。字符常量总是以‘/0‘结束。注意不能将字符串常量赋给字符常量。“0”和‘0’是不同的。

枚举常量,可以通过枚举类型来定义。定义枚举类型的语法是先写关键字enum,后跟类型名,花括号,花括号括起来的里面是用逗号隔开的每个枚举常量值,最后以分号结束定义。例如,enum color{redbluegreen}

          Color是枚举类型名,它不是变量名,所以不占内存空间。在内存中,red等各个符号常量表示各个枚举值,以整数表示。如果没有专门的规定,第一个符号常量的枚举值就是0,其他枚举值依次为1往上加。但,变量的取值只能取枚举类型定义是规定的值。不能用整数值赋给枚举变量。

4.  常量定义

常量是常数或代表固定不变值得名字。注意变量名不能放在赋值语句的左边。

关于#define,在c中,#define pi 3.1415926这条指令的格式是#define后面跟一个常量名再跟一串字符,中间用空格隔开,由于它不是c++语句,所以行末不用分号。

5.  Printfscanf函数

Printf函数的一般格式为printf(格式控制字符串,输出项1………)。例如printf(“%d%d”,ab);

格式控制字符串中有格式说明也有普通字符。它的作用是将输出的数据转换成制定的格式输出,包括%d(输出10进制整数),%o8进制),%x16进制),%u(无符号10进制整数方式输出),%c(以字符方式),%s(以字符串方式),%f(以小数方式),%e(以指数方式)。

Scanf的一般形式为:scanf(格式控制字符串,地址1……)地址n是变量的地址,格式控制字符串的含义同前。例如,scanf(“%d %d”,&a,&b);scanf(“%d %d”,&a,&b);两个输入项之间一般涌空格分开。如果规定了分割字符,如逗号,则必须以逗号分开。

 

                      3 表达式和语句

 1.增量和减量

    增量减量操作符表示为:++--。表示加1和减1。增量操作符有前增量和后增量之分。前增量操作的意义为:先修改操作数使之增1,然后将增1过的值作为表达式的值。后增量操作的意义为:先将变量的值作为表达式的值确定下来,再增加1    

但,++a++//error,由于后增量操作返回的值是原先a的值,而后a的值发生了变化,故返回的不能是当前a,只能使过去的a值,不能为左值。由于增量和减量操作包含有赋值操作,所以操作数不能为常量,它必须是一个左值表达式。

                                

                               5章 函数

1.函数概述

   把相关的语句组织在一起,并给他们注明相应得名称,利用这种方法把程序分块,这种形式的组合就称为函数。函数的使用是通过函数调用来实现的。但c语言中不允许函数定义嵌套,即在函数定义中再定义一个函数是违法的。

2.函数原型

   函数原型是一条程序语句,即它必须以分号结束。它由函数返回类型,函数名和参数表构成。参数表包含所有参数的数据类型,参数之间用逗号分开。在c中,函数声明就是函数原型。函数原型不必包含参数的名字,而只要包含参数的类型。函数必须先声明才能被使用

函数的返回值也称函数值。返回的不是函数本身,而是一个值。Return后面跟返回值。在这里,return还起到改变计算顺序的作用。因为return是返回语句,它将退出函数体,所以该语句之后的语句不会执行了。Return后面的表达式并不直接替换调用函数,而是先经过求值计算,必要的时候进行类型装换,然后将其存放到内存的某个区域。该区域视编译器的不同而不同。也视返回类型的不同而不同。在存放到一个专用的区域后,再将其变量的地址传给调用函数,以使调用函数把它作为函数返回值。

Main的返回值。Main是特殊的函数,它由操作系统调用,返回操作系统。函数头void main()是说,不返回任何值给操作系统,所以,在main()函数体的最后,无须“return 1;”之类的语句。如果函数头为int main()或main(),则函数体的最后必须给出“return 1;”之类的语句。

3.全局变量和局部变量

   一个程序将操作系统分配给其运行的内存块分为4个区域:

(1)            代码区,存放程序代码

(2)            全局数据区,存放程序的全局数据和静态数据。

(3)            堆区,存放程序的动态数据。

(4)            栈区,存放程序的局部数据。

   全局变量,在函数外边访问的变量被认为是全局变量,并在程序的每个函数中是可见的。全局变量存放在内存的全局数据区。全局变量由编译器建立,并且初始化为0,如果一个函数修改了全局变量,则所有其他的函数都会看到修改后的值。全局变量在主函数main()运行之前就开始存在。但全局变量定义之前的所有函数定义,不会知道该变量。

   局部变量,在函数内部定义的变量仅在函数内可见的,另外,局部变量的修饰类型是auto,表示该变量在栈中分配空间,但习惯上都省略auto。函数种的局部变量存放在栈区。在函数运行时,局部变量在栈区被分配空间,函数退出时,局部变量随之消失。

4.函数调用机制

  函数调用的整个过程就是栈空间操作的过程。函数调用时,c++首先:

(1)            建立被调用函数的栈空间。

(2)            保护调用函数的运行状态和返回地址。

(3)            传递参数。

(4)            将控制转交被调函数。

函数在返回时,将把返回值保护在临时变量空间中(如果有返回值的话),然后恢复调用函数的运行状态,释放栈空间,使其属于函数栈空间的一部份,最后根据返回地址,回到调用函数。

5.静态局部变量

在局部变量前加上“static”关键字,就成了静态局部变量。静态局部变量存放在内存的全局数据区。函数结束时,静态局部变量不会消失,每次该函数调用时,不会为其重新分配空间。它始终驻留在全局数据区,知道程序运行结束。但静态局部变量只能在定义它的函数中可见。

6.内联函数

内联函数也称内嵌函数,它主要是解决程序的运行效率。在函数声明时,函数前加inline,内联函数必须在被调用之前声明或定义。内联函数中,不能含有复杂的结构控制语句,如switchwhile。递归函数是不能被用来做内联函数的。内联函数只适合于只有1~5行的小函数。

c中,常用的预处理语句#define来代替一个函数定义。例如:#define MAX(a,b) ((a) > (b) ? (a) : (b))。该语句使得程序中出现MAX(a,b)的地方都被宏定义中后面的表达式所替换。

7.重载函数

对于在不同类型上作不同运算而又用相同名字的情况,则称之为重载。在调用一个重载函数时,编译器必搞清楚汉书明究竟是指哪个函数,按下面3个步骤的先后顺序找到并调用那个函数:

(1)            寻找一个严格的匹配,如果找到了,就用那个函数。

(2)            通过内部转换寻求一个匹配,只有找到了,就用那个函数。

(3)            通过用户定义的转换寻求一个匹配,若能查出有唯一的一组转换,就能用那个函数。

(4)            重载函数至少在参数个数,参数类型或参数顺序上有所不同。

8.默认参数的函数

     C可以给函数定义默认参数值。当又有声明又有定义时,在定义中不允许默认参数。

     如果一个函数中有多个默认参数,则形参分布中,默认参数应从右至左逐渐定义。当调用函数时,只能向左匹配参数。

     默认值可以是全局变量,全局常量,甚至是一个函数。不可以是局部变量,因为默认参数的函数调用是在编译时确定的,而局部变量的位置与值在编译时无法确定。

 

                            6章 程序结构

1.外部存储类型

     构成一个程序的多个源文件之间,通过声明数据或函数为外部的(extern)来进行沟通。它表示该变量不再本文件中分配空间,而在程序的其他文件中分配空间。默认的函数声明或定义总是extern的,它告诉连接程序,在所有组成该程序的文件中搜索该函数的定义。带extern的变量说明是变量声明,不是变量定义。

2.静态存储类型

     在全局变量前加一个static,使该变量只在这个源文件中可用,称之为全局静态变量,也就是静态全局变量。静态全局变量对组成该程序的其他源文件是无效的。

     函数的声明和定义默认情况下在整个程序中是extern。有时候,你可能需要使某个函数只在一个源文件中有效,不能被其他源文件所用,这时在函数前面加上static。在文件作用域下声明的inline函数默认为static存储类型。在文件作用域下声明的const的常量默认为static

 

                               7章 数组

1.数组定义

数组是一个由若干同类型变量组成的集合。说明方法为:类型说明符 数组名[常量表达式];常量表达式表示元素的个数,即数组长度。数组下标从0开始,下标是数组元素到数组的偏移量。常量表达式可以包含枚举常量和字符常量,该常量表达式的值是在编译时确定的。

2.初始化数组

数组可以初始化,即在定义时使它包含程序马上能使用的值。初始化数组的值得个数不能多于数组元素个数,初始化数组的值也不能通过跳过逗号的方式来省略,在c中是允许的,在C++中不允许。例如:

int array1[5] = {1,2,3,4,5,6};//error

int array2[5] = {1,,2,3,4};//error

int array3[5] = {1,2,3,};//error

int array4[5] = {};//error

int array5[5] = {1,2};//ok

当初始化字符数组时要注意最后的’/0’,要为其分配空间。Char array[5] = “hello”

有初始化的数组定义可以省略方括号中的数组大小。但在编译时2必须知道数组的大小,一般是花括号之间的元素个数。

3.向函数传递数组

无论何时,将数组作为函数参数传给函数,实际上只是把数组的地址传给函数。

4.二维数组

     需要两个下标才能标示某个元素的数组称为二维数组。第一个下标表示行,第二个下标表示列。如果对全部元素都赋初值,则定义数组时对第一维的大小可以省略,但第二维的大小不能省略。由于二维数组在内存中是线性排列的,传递一维数组和传递二维数组都是传的地址,所以可以在被调用的函数中用单循环来遍历二维数组中的所有元素。

 

                            8章 指 针

1.指针概念

指针变量的定义语句,由数据类型后跟星号,再跟随指针变量名组成。在指针定义中,一个*只能表示一个指针。

建立指针包括定义指针和给指针赋初值。用&操作符可以获取变量的地址,指针变量用于存放地址。

间接引用指针时,可获得由该指针指向的变量内容。*放在可执行语句中的指针之前,称为间接引用操作符,*放在指针定义中时,称指针定义符。非指针变量不能用间接引用操作符,因为*只能用于地址。间接引用的指针既可用于右值,也可用于左值。

指针变量的地址,指针也是变量,是变量就具有内存地址。*iPtr的类型是整型,指针iPtr指向该整数,所以iPtr的类型是整型指针,而iPtr的地址的类型是整型指针的地址,即指向整型指针的指针。指针的地址就是二级指针。指针值不是整型数,它是地址类型,不能将整型地址转换为整型数。

指针变量初始化的值是指该指针类型的地址值。*操作符在指针上的两种用途要区分开:定义或声明时,建立一指针;执行时,间接引用一指针。指针使用前,要进行初始化。指针忘了赋值比整型变量忘了赋值危险的多。

指针是有类型的,给指针赋值,不但必须是一个地址,而且应该是一个与该指针类型相符的变量或常量的地址。指针具有一定类型,它是值为地址的变量,该地址是内存中另一个该类型变量的存储位置。或者说指针是具有某个类型的地址。

2.堆内存分配

堆是内存空间,区别于栈区,全局数据区和代码区的另一个内存区域。堆允许程序运行时申请某个大小的内存空间。

函数malloc()c程序获得堆内存的一种方法,它在alloc.h头文件中声明。函数free()把内存释放回堆以供其他部分占用。

3CONST 指针

指向常量的指针(常量指针),在指针定义语句的类型前加const,表示指向的对象是常量。定义指向常量的指针只能限制指针的间接访问操作,而不能规定指针指向的值本身的操作规定性。

指针常量,在指针定义语句的指针名前加const,表示指针本身是常量。在定义指针常量时必须初始化。

指向常量的指针常量,表示指针本身和对象都是常量,不能作为左值。

4.指针与函数

返回指针的函数称为指针函数。指针函数不能把在它内部说明的具有局部作用域的数据地址作为返回值。可以返回堆地址,可以返回全局或静态变量的地址,但不要返回局部变量的地址。

5void指针

Void指针是空类型指针,它不能指向任何类型,即void指针仅仅只是一个地址。所以空类型不能进行指针运算,也不能进行间接引用。由于其他指针包含地址信息,所以将其他指针的值赋给空类型指针是合法的,反之,将空类型指针赋给其他指针则不允许,除非进行显式转换。

6.字符指针

c中,有两类字符串,一类是字符数组,一类是字符串常量。由引号表示,但不是用来初始化数组的字符串,是字符串常量。用来给数组初始化的不是字符串常量。字符串常量的类型是指向字符的指针。字符串常量通常存放在内存data区中的const区。当编译器遇到一字符串常量时,就把它放到字符串池中,以‘/0’作为结束符,记下起始地址,在所构成的代码中使用该地址。这样字符串常量就变成了地址。由于字符串常量的地址属性,所以两个同样字符组成的字符串常量的地址不相等的。所以字符指针,只要输出字符指针就是输出字符串,输出字符指针的间接引用,就是输出单个字符。

 

                       9章 引 用

1.引用的概念

引用是个别名,当建立引用时,程序用另一个变量或对象的名字初始化它。从那时起引用的恶改动就是目标的改动。为建立引用,先写上目标的类型,后跟引用运算符“&”,然后是引用的名字。引用能使用任何合法变量名。

如果程序寻找引用的地址,它只能找到所引用的目标的地址,然而建立引用时必须进行初始化并且决不会再关联其他不同的变量。

不能使用引用的地方:

(1)            void不允许。Void在语法上相当于一个类型,但没有任何一个变量或对象,其类型为void

(2)            不能建立引用的数组。

(3)            引用本身不是一种类型,所以没有引用的引用,也没有引用的指针。

(4)            引用不能用类型初始化。引用是变量的引用,不是类型的引用。

程序决不能给引用本身重新赋值,使他指向另一个变量,因此引用总是const

2.引用的概念

传递引用给函数与传递指针的效果一样,传递的是原来的变量或对象,而不是在函数作用域内建立变量或对象的副本。但是因为引用隐藏了函数使用的参数传递的类型,所以无法从所看到的函数调用判断其是值传递还是引用传递。

Void fn(int s)

{

}

Void fn(int& t)

{

}

Void main()

{

  Int a = 5;

  Fn(a); //error匹配哪一个函数

}

3.用引用返回值

函数返回值时,要生成一个值得副本。而用引用返回值时,不生成值的副本。返回一个引用使得一个函数调用表达式成为左值表达式。

4.返回堆中变量的引用

对引用的初始化,可以是变量,可以是常量,也可以是一定类型的堆变量。但是,由于引用不是指针,所以直接从堆中获得的变量空间来初始化引用是错的。如果new不能在堆空间成功的获得内存分配,它返回null。因为引用不能是null,在程序确认它不是null之前,程序不能用这一内存初始化引用。

用堆空间来初始化引用,要求该饮用在适当时后释放堆空间。

对于使用堆的引用,有下面的经验:

(1)            必要时用值传递参数。

(2)            必要时返回值。

(3)            不要返回有可能退出作用域的引用。

(4)            不要引用空目标。

 

                                   第十章 结 构

1.结构

结构是用户自定义的新数据类型,除此之外,它可与intfloat等基本数据类型同等看待。声明结构类型时,首先指定关键字struct和结构名,然后用一对花括号将若干个结构成员数据类型说明括起来。

在通常情况下,结构声明在所有函数之外,位于main()函数之前。这使新声明的三数据类型在程序的任何地方都可以被使用。声明一个结构并不分配内存,内存分配发生在定义这个新数据类型的变量中。

一旦通过定义相应结构变量,分配了空间,就可以使用点操作符“.”来访问结构中的成员。左操作数为结构类型变量,右操作数为结构中的成员。

在数组中,数组是不能彼此赋值的。这主要是因为数组名是一个常量指针,不允许被赋值。结构就不同,它大小固定,可以被赋值。

2.结构与指针

根据结构类型可以定义一个变量,是变量就有地址。结构不象数组,结构变量不是指针。同过取地址操作,可以得到结构变量的地址,这个地址就是结构的第一个成员地址。

当用点操作符时,它的左边应是一个结构变量,当用箭头操作符时,它的左边应是一个结构指针。

结构成员不能是自身的结构变量,但可以用自身结构指针作为成员。

 
原创粉丝点击