C语言要点归纳

摘自:《C语言入门经典(第4版)》(美)lvor Horton. 著  杨浩.  译  北京.清华大学出版社

【1】知识要点1

  1. C程序创建4个基本步骤:编辑,编译,链接,执行。
  2. 编辑过程就是创建和修改C程序的源代码,我们编写的程序指令称为源代码。C编译器带一个编辑器,提供编写、管理、开发与测试程序的环境,有时也称为“集成开发环境(IDE)”。
  3. 在UNIX或Linux上,最常用的的文本编辑器是vi,也可以使用emacs编辑器。
  4. 编译器将源代码转换成机器语言,产生源文件,编译器输出结果称为对象代码(object code),存放他们的文件称为对象文件(object file)。这些文件扩展名在Windows环境中是.obj,在Linux/UNIX环境中是.o
  5. 链接器(Linker)将源代码文件中由编译器产生的各种模块组合起来,再从C程序库中添加必要的代码模块,将其组合成一个可执行的文件。如果程序太大,可拆成几个源代码文件(分别编译),再用链接器连接起来,组成程序的源文件通常会用同一个项目名称集成,这个项目名称用于引用整个程序。链接成功后产生一个可执行文件Windows环境下,可执行文件的扩展名为.exeUNIX环境下,没有扩展名,但它是一个可执行的文件类型。
  6. int main(void)    关键字(也称保留字)int表示main()函数返回一个整数值,执行完main()函数后返回的整数值表示返回给操作系统的一个代码,表示程序的状态。void表示没有给函数main()传递任何数据
  7. return 0;    /*return语句结束main()函数的执行,把0返回给操作系统,返回0表示程序正常终止,返回非0表示异常*/

【2】知识要点2

  1. 联合测试各个程序模块,称为集成测试(integration testing)
  2. 计算机执行程序时,组成程序的指令和程序所操作的数据都必须存储到某个地方,即执行程序时存储程序及数据的地方。这个地方就是机器的内存,也称为主内存(main memory),或者随机访问存储器(Random Access Memory,RAM
  3. 计算机中还有另一种存储器,即只读存储器(Read-Only Memory,ROM),ROM不能修改,只能读取其内容,或让计算机执行包含在ROM中的指令。ROM中的信息是在制造机器时放进去的,主要是一些程序,用来控制连接到计算机上的各种设备的运作,这些程序称为,计算机的基本输入输出系统(Basic Input/Output System,BIOS)
  4. 变量是计算机里一块特定的内存,是由一个或多个连续的字节所组成,每个变量都有一个名称,可以用该名称表示内存的这个位置,以提取它包含的数据或存储一个新数值。
  5. 在计算机中,所有的值都存储为二进制数
  6. 变量名可以包含的字符数取决于编译器,遵循C语言标准的编译器至少支持31个字符,不超过该长度即可。
  7. 相同类型的不同变量总是占据相同大小的内存(字节数)
  8. 计算机的内存组织为字节

【3】知识要点3

  1. #define语句中的标识符都是大写,例,#define PI 3.14159f (定义一个常量,或者采用,const float pi = 3.14159f; 注:变量名前加上const关键字,可以固化变量的值)
  2. 每个无符号整数类型的级别都与对应的带符号整数类型(类型指的是,值域类型)相同。例如,unsigned int类型的级别与int类型相同。
  3. char类型的变量有双重性,既可解释为一个字符,也可解释为一个整数,例如,char character = 67;等价于char character = 'C'; character = character + 3;可以对char类型的值进行算术运算,同时仍把它当做一个字符。
  4. math.h头文件包含各种数学函数的声明,所有的函数都返回一个double类型的变量。
  5. if语句的控制表达式要生成一个布尔结果,所以编译器要将If表达式的数值结果转换成_Bool类型。
  6. Long test = 0L;//如果使用0代替0L,编译器就会插入代码,将int类型的0转换为long类型。
  7. a的ASCII码(十进制)值是97,A的ASCII码值是65.
  8. 运算符说明,“.”按对象选择成员,“->”按指针选择成员,Sizeof,表达式或类型的字节数。
  9.  “&”是按位与,“&&”是逻辑与;“^”是按位异或,“|”是按位或,“||”是逻辑或。
  10. 按位运算符,只能用于整数类型。按位与&、按位或|运算符的一个主要用途是测试并设置整数变量中的各个位,使用各个位存储涉及二选一的数据。
  11. 定义“掩码”,即首先定义一个值,用于选择需要的位,在掩码中,希望保持不变的位置上包含1,希望舍弃的位置上包含0,接着对这个掩码与选中位的值,执行按位与操作。
  12. %运算符只能用于整数。long是long int的缩写,占4个字节,P48页

【4】知识要点4

  1. for(;;);循环永不停止,经常结合break;语句使用。
  2. 每次调用rand()函数,它都会返回一个随机整数,这个值在0到定义的RAND_MAX之间,由rand()函数产生的整数称为伪随机数。P154页
  3. 键盘缓冲区是用来存储键盘输入的内存,scanf()函数是在键盘缓冲区查找输入数据,而不是直接从键盘上读取数据。
  4. 标准输入和输出-键盘和屏幕-有两个缓冲区:一个用于输入,另一个用于输出,标准输入输出流分别称为stdin和stdout。要指定键盘输入缓冲区,只需使用名称stdin。标准库函数fflush()就是用于清除缓冲区的。清除输入缓冲区的内容可以使用:fflush(stdin);
  5. 数组是相同数据类型的元素按一定顺序排列的集合。数组名,指定了存储数据项的内存区域地址,结合地址和索引值,就可以找到每个元素,索引值表示各个元素与数组开头的偏移量。
  6. 数组元素的地址是数组开始的地址加上元素的索引值乘以数组中每个元素类型所需的字节数。分配给每个元素的内存量取决于数组所含的变量的类型。
  7. 格式指定符%p,来输出变量的地址,即内存地址,其值为十六进制,内存地址一般是16,32,或64位,地址的大小决定了可以引用的最大内存量。例如:int number = 0;要输出变量number的地址,应使用输出格式指定符%p,它以十六进制格式输出内存的地址。
  8. 字符串的长度永远比字符串中的字符数多1
  9. printf()函数遇到第一个空字符\0时,就会停止输出。即在遇到第一个\0时,就表示字符串已经结束了。
  10. 要引用存储在数组中的字符串时,只需使用数组名即可。
  11. 用while循环确定字符串长度,P215页
  12. sizeof是C/C++中的一个操作符(operator),返回一个对象或类型所占的内存字节数,即判断数据类型或者表达式长度符。例如P217页
  13. 标准库中strlen()函数可以确定字符串的长度。
  14. 要对字符串执行算术赋值操作,必须逐个元素地把一个字符串复制到另一个字符串中。
  15. 二维数组存储字符串,第一维指定字符串的数目,数组的每一行都用来存储一个字符串。P218页
  16. size_t是strlen()函数的返回值,也是运算符sizeof的返回类型,(如果返回类型不同,则是编译器不同的原因)
  17. 类型size_t定义为一个无符号的整数类型unsigned int
/*可移植性高的代码*/
size_t count2 = 0;
count2 = strlen(str2);

【5】知识要点5

  1. 字符串的比较是基于它们的字符码
  2. 指针是含有地址的变量(指针就是地址),它含有内存中另一个包含数值的位置的引用。
  3. 标准库函数gets()将输入的字符串读入数组buffer(在字符串的末尾会自动附加一个'\0'字符)。scanf()接收键盘输入,但不适合读入字符串,因为它会将空格解释为输入值的末尾,而gets()函数的优点是可以从键盘读入所有字符(包括空白),直到按下回车键为止,然后将字符串存储到其参数指定的区域中。如果gets()函数在读入输入时发生错误,就会返回NULL(通常它会返回传给它的参数的地址)。程序中因此判断举例:P231页
  4. fgets()函数,允许指定输入字符串的最大长度。这个函数可用于任意种类的输入字符串,而gets()只能读取标准输入流stdin;所以还必须指定fgets()的第三个参数,说明要读取的输入流。如果从键盘上读取字符串,fgets()读取的字符串比gets()读取的字符串多一个字符,另外,在输入时按下回车键,gets()读取的输入会附加一个空字符串\0,而fgets()读取的输入会附加\n\0。程序中因此判断举例:P231页
  5. 宽字符串,存储在wchar_t类型的数组中,wchar_t字符占用2个字节,要使用printf()将字符输出到屏幕上,必须使用%S格式指定符,而不是用ASCII字符串的%s,如果使用了%s,printf()函数就假定字符串包含单字节字符,出错。
  6. 可以存储地址的变量称作指针(pointers)。每个指针都和某个变量类型相关联,也只能用于指向该类型的变量。类型名void表示没有指定类型,所以void*类型的指针可以包含任意类型的数据项地址。类型void*常做参数类型,或以独立于类型的方式处理数据的函数的返回值类型,任意类型的指针都可以传送为void*类型的值,在使用它的时候,再将其转换为合适类型。
  7. int *pointer;//声明一个指向int类型变量的指针。pointer变量的类型是int *,它可以存储任意int类型变量的地址。int *pointer = NULL;//初始化pointer,使它不指向任何对象。NULL是标准库中定义的一个常量,对于指针它表示0,NULL是一个不指向任何内存位置的值,这表示,使用不指向任何对象的指针,不会意外覆盖内存。
  8. *运算符的作用是访问存储在pointer(指针变量)中的地址的数据,*运算符称为间接运算符,有时也称取消引用运算符。
  9. 声明指针(比如:long *pnum = NULL;)时,一定要初始化它们,使用未初始化的指针存储数据项是很危险的,在使用指针存储一个值时,谁也不知道会覆盖什么内容。
  10. 指向常量的指针,用const关键字指定,如:long value = 9999L;const long *pvalue = &value; 定义后,pvalue指向的值不可更改,但是可以对value进行任意操作。即改变了pvalue指向的值,但不能使用pvalue指针做这个改变。指针本身不是常量,所以仍可以改变它指向的值。
  11. 在C/C++中,声明常量指针两种形式:(1)const int *p;(2)int const *p; const的位置在指针声明运算符*的左侧。只要const位于*的左侧,无论它在类型名的左边或右边,都声明了一个指向常量的指针,叫做常量指针。例如:定义int a,b;const int *p=&a; *p不可更改,p可修改,如p=&b,在使用字符串处理函数时,函数的声明,它们的参数一般声明为常量指针,比如int strcmp(const char *str1, const char *str2);            
  12. 在C/C++中,定义指针常量: int a; int *const p=&a; 因为指针常量是一个常量,声明的时候要赋初始值。赋值后,这个常量再也不能指向别的地址。虽然指针常量的值不能变,但是它指向的对象是可变的,我们并没有限制它指向的对象是常量。*p可以修改,如*p=8; p不可以被修改。
  13. const *  表示带*运算对象的是常量,也就是*p 不可变 (暗示p可变,p不带‘*’ 嘛)
  14. * const 变量名  表示变量名是常量  也就是p不可变 (暗示*p可变,const没有修饰‘*“ 嘛)
  15. 在C/C++中,声明指向常量的指针常量(*p 和 p均不可改变),例如:
     const int a = 25;
     const int *const b = &a;

【6】知识要点6

  1. multiple[n]与*(multiple+n)是相同的。P260页,数组名称是一个固定的地址,而不是一个指针。
  2. 在计算机内存中,是没有多维数组的概念的。
  3. 只有使用指针,才能动态分配内存。
  4. 在程序的执行期间分配内存时,内存区域中的这个空间称为堆(heap)。还有另外一个内存区域,称为堆栈(stack)。其中的空间分配给函数的参数和本地变量。在执行完该函数后,存储参数和本地变量的内存空间就会释放。堆中的内存是由程序员控制的。
  5. 堆内存是用malloc或new分配的内存空间,栈是用关键字定义出变量的内存空间。有些时候必须用堆内存,如:链表。堆最好是用来存放大数据,而栈本身就小,但速度快。
  6. 堆上分配的内存会在程序结束时自动释放,使用完内存后应该立即释放。当动态分配了一些内存时,没有保留对它们的引用,就会出现内存泄漏,此时无法释放内存,常发生在循环内部。
  7. 运行时分配内存的最简单的标准库函数是malloc()。使用这个函数时,需要在程序中包含头文件。使用malloc()函数需指定要分配的内存字节数作为参考。这个函数返回所分配内存的第一个字节的地址。因为返回的是一个地址,所以可使用指针。
  8. 在C/C++中,%u表示无符号10进制整数,%d或%i表示有符号10进制整数,后者可以自动将输入的8进制或16进制转换为10进制。
  9. size_t是标准C库中定义的,应为unsigned int,在64位系统中为:long unsigned int, size_t类型通常用于循环、数组索引、大小的存储和地址运算。
  10. 使用动态分配的内存的基本规则:(1)避免分配大量的小内存块,分配堆上的内存有一些系统开销,因此分配小的内存块比分配几个大的内存块的系统开销大;(2)仅在需要时分配内存。只要使用完堆上的内存块,就释放它;(3)确保释放已分配的内存。在编写分配内存的代码时,就要确定在代码的什么地方释放内存;(4)在释放内存之前,确保不会无意中覆盖堆上分配的内存的地址,否则程序就会出现内存泄漏,在循环中分配内存,需特别小心。
  11. free()函数与malloc()函数是互补的,它释放了malloc()分配的内存,它只需要把所分配的内存指针作为参数,虽然内存在程序结束时会自动释放,但是内存最好在不需要时立即释放,当然,一旦用这个方式释放内存后,就不能再使用它,所以立刻将该指针设定成NULL。
  12. 处理多个字符串时,可以在堆上使用指针数组存储对字符串的引用。
  13. 创建一个指针数组:char *pS[3] = { NULL };//声明了一个数组pS,它包含3个指针。初始化列表中只有一个值NULL,它将任意大小的指针数组中的所有元素都初始化为NULL。
  14. 使用全局变量指定数组大小时,该变量必须声明为const,才能用来指定数组的大小,因为数组的大小只能用常量表达式指定。对应P280页
  15. 在C/C++中,全局变量如果没有初始化,则默认为0,而局部变量如果没有初始化,则是遗留在内存中的垃圾数据,或者是一个很大的负数,局部的int默认的是-858993460,即0xcccccccc
  16.  VC的DEBUG会把未初始化的指针自动初始化为0xCCCCCCCC,汉字“烫”的编码正好是1100110011001100(常见于忘记赋值或数组越界的情况),而全局变量链接时已分配空间,程序运行时,操作系统的加载器,负责把链接器分配给全局变量的虚拟内存空间,映射到一个初始化为零的页面,即初始化为0。
  17. 全局和静态的默认初始化都是靠加载机制实现的,另外,未初始化的符号在目标文件的bss段中,而初始化的符号在data段中。
  18.  局部变量存在于(堆栈)中,全局变量存在于(静态区)中,动态申请数据存在于(堆)中。
  19. 当自动变量或者静态变量和全局变量同名时,它们会隐藏同名的全局变量。如果已经定义全局变量,若调用的函数里面没有定义同名的自动变量,而用到同名的变量时,那么就使用该全局变量。P346页
  20. 函数调用自己称为递归。


112.标准头文件:函数详见P355页

                   输入输出函数
                  字符串处理函数
                  内存分配函数
                 bool类型和布尔值true和false
                   字符分类函数
                    数学浮点函数
                 支持复数
                  支持变元个数可变的函数的宏
                  宽字符转换函数

【7】知识要点7

  1. C语言没有输入输出能力,所有这类操作都由标准库中的函数(独立于设备之外)提供。
  2. 链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
  3. 利用结构成员指针生成一个结构链,在这个链中,每个结构的next成员都指向下一个结构,最后指向的结构中的next指针设定成NULL,这称为链表。
  4. 在需要处理数量未知的结构的应用程序中,链表非常有用,链表的主要优点是内存的使用和便于处理。存储和处理链表所占用的内存量最少,即使所使用的内存比较分散,也可以从一个结构进入下一个结构。因此,链表可以用于同时处理几个不同类型的对象,每个对象都可以用它自己的链表来处理,以优化内存的使用。但是链表的数据处理的速度比较慢,尤其是要随机访问数据时,速度更慢。
  5. 双向链表:在单向链表的基础上,除了指向下一个结构的指针外,在每个结构中再添加一个指针,存储前一个结构的地址。从而可以双向遍历链表。见P428“双向链表”的实例分析
  6. 共享内存的3种情况:(1)使用几个变量时,但其中只有一个变量在任意给定的时刻都有有效值;(2)程序处理许多不同类型的数据,但是一次只能处理一种,要处理的类型在执行期间确定;(3)要在不同的时间访问相同的数据,但是在不同的情况下,该数据的类型是不同的。
  7. 联合:C语言中允许多个不同变量共享同一内存区的功能。
  8. 匿名联合:声明一个结构类型,其中包含一个没有标记符名称的联合,这个联合的实例只能存在于结构的实例之中,这种联合常常称为匿名联合。
  9. C的标准库包含了一些处理时间与日期的函数。根据计算机的硬件计时器提供各种不同格式的输出。 “函数原型等内容分析”见P547页

你可能感兴趣的:(C/C++,c语言)