第七章: 分支控制java
1.while((c=getchar()) != '' && c!= '\n'): 循环读入字符,直到出现第一个空格或者换行符 while(getchar()!='\n') continue 跳过输入行的剩余部分。程序员
2.逻辑表达式是从左到右求值的,一旦发现有使表达式为假的因素,当即中止求值(这点和java是不一样的)。好比,if(number !=0 && 12/number ==2),c语言能够保证右边不会出现除0错误。编程
3.&&和||运算符是序列的分界点。好比while(x++<10 && x+y<20), 在对右边表达式求值以前,先把x的值增长1.数组
4.用&&来测试范围,好比 if(range>=90 && range <=100), 不要用if(90 <= range <= 100),这种写法没有语法错误,可是有语义错误,由于编译器会解释为(90 <= range) <= 100, 因此最终值老是为真。ide
5.控制合法输入,读入一个数据,while(scanf("%d",&d)==1),判断两个输入:while(scanf("%f","%f",&length,&width) == 2)函数
6.break 语句实际上是switch语句的附属物测试
第八章:字符输入输出spa
1.缓冲分为两类:指针
彻底缓冲:缓冲区满时被清空,一般用于文件传输中,缓冲区块的大小取决于系统rest
行缓冲: 遇到一个换行字符时将清空缓冲区。键盘输入是标准的行缓冲,所以按下回车键将清空缓冲区。
2.如今的某些文件可能还会以 “Ctrl+z”来标记文件结束,也可能没有(^z)。第二种方式是存储文件的大小信息。
3.在大多数的Unix系统中,在一行的开始键入Ctrl+D会致使传送文件尾信号,能够用以下的方式:#include<stdio.h> while((ch=gechar()) != EOF)
4.令程序与文件一同工做有两种方式:一:明确的使用打开文件等专门的函数 二:重定向:将stdin流(一般是从键盘输入)从新分配至文件。输入重定向能使用文件代替键盘做为输入,输出重定向可使程序用文件代替屏幕做为输出。
5. < 是Unix,Linux和Dos的重定向运算符。如 a.out < words, 该运算符把words文件与stdin流关联起来,将该文件的内容引导至a.out程序,因为C 将文件和I/O设备至于相同的地位,因此这个文件如今就是I/O设备。
6.使用重定向运算符>和<时,输入不能来自一个以上的文件,输出也不能定向至一个以上的文件
7.其它的运算符: (>>) 使得能够向一个文件的末尾追加数据;管道运算符 (|)能够将第一个程序的输出与第二个程序的输入链接起来
8.getchar()读取每一个字符,包括空格,制表符和换行符,scanf()再读取数字式则跳过空格,制表符和换行符。putchar()
9.若是混合使用scanf()和getchar()函数,那么当调用getchar()以前scanf()刚好再输入缓冲中留下一个换行符,所以会产生问题,可是当咱们知道了这个问题,能够经过编程手段来避免。
第九章:函数
1.一个函数一般包括三部分:函数原型,告知编译器函数的类型,函数调用,致使函数的执行,函数定义,确切的制定了函数的具体功能
2.在程序中能够把函数原型放在main()以前,也能够放到main()之中,能够放到变量声明的任何位置,这两种方法都是正确的。
3.在函数原型中能够根据您本身的喜爱省略变量名,如 void show(char, int)
4.被调用函数使用的值是从调用函数中复制而来的,因此无论在被调用函数中对复制数值进行什么操做,调用函数中的原数值不会收到任何影响。
第十章:数组和指针
1.有关数组初始化:int no_data[size]: 若是不进行数组初始化,则和未初始化的普通变量同样,其中存储的是无用的数值;int some_date[4]={1492,1066},若是部分初始化,则编译器作的很好,多余的数组元素被初始化为0. int some_data[4]={1,2,3,4,5,6},这种初始化列表中项目的个数大于数组的大小,编译器会绝不留情的认为这是一个错误,可是能够用省略括号中的数字的方式来让编译器自动匹配数组大小。int some_data[]={1,2,3,4,5,6}。C99加入了一个新的特性:int days[MONTHS]={32,28,[4]=31,30,31,[1]=29}.有两点须要说明:1.[4]=31,30,31代表不只days[4]=31,并且days[5]=30,days[6]=31. 2.后面的指定会覆盖前面的指定。
2.为何C不检查数组边界? 在程序运行前,索引的值可能还没有肯定下来,因此编译器此时不能找出全部的索引错误。为保证程序的正确性,编译器必须在运行时添加检查每一个索引是否合法的代码,这回致使程序的运行速度减慢。
3.对于二维数组的初始化,也能够省略内部的花括号,只保留最外面的一对花括号,在初始化时,按照前后顺序来逐行赋值,所以前面的元素首先获得赋值,直到没有数值为止。
4.为何在声明指针的时候必须指明指针指向的数据类型?在C中,对一个指针加1的结果是对该指针增长一个存储单元。对于数组而言,地址会增长到下一个元素的地址,而不是下一个字节。这就是为何在声明指针时必须声明它所指向对象的类型。计算机须要知道存储对象所用的字节数,因此只有地址信息是不够的。
5.在函数原型中,因为名称能够省略,则下面四种原型是等价的:
a) int sum(int *ar, int n)
b) int sum(int *, int)
c) int sum(int ar[], int n)
d) int sum(int [], int)
在定义函数时,名称是不能够省略的,所以在定义函数时如下两种方式等价:
a) int sum(int *ar, int n)
{
//code
}
b) int sum (int ar[], int n)
{
//code
}
其中,有一点提出的是, 在函数原型和函数定义这两种场合中, int* ar 和 int ar[]是等价的。
6. c中数组和指针的关系容许您在数组符号中使用指针ar。
int sum(int *ar, int n)
{
ar[i] = ...
}
但在这种状况下,sizeof ar 为 4. 即便为
int sum(int ar[], int n)
{
}
这种状况下sizeof ar 任然为4.
然而,若是在定义的区域内查看sizeof,如:
int marbles[10] = {1,2,3,4,5,6,7,8,9,10}
printf("The size of marbles is %zd bytes.\n.", sizeof marbles);
这种状况下,会输出40.(10 * 4)
第12章:存储类,连接和内存管理
1.文件做用域变量有时也被称为全局变量。
2.一个C变量具备下列连接之一:外部连接(external linkage)(static), 内部连接,或空连接。具备代码块做用域或者函数原型做用域的变量具备空连接,觉得着他们是由其定义所在的代码块或函数原型所私有的。具备文件做用域的变量可能有内部或者外部连接。一个具备外部连接的变量能够再一个多文件程序的任何地方使用。一个具备内部连接的变量能够在一个文件的任何地方使用。
3.在内层代码块中定义的名字是内层代码块所使用的变量,咱们称之为内层定义覆盖(hide)了外部定义,但当运行离开内层代码块时,外部变量从新恢复做用。
4.可能须要 -std=C99来激活编译器的C99支持。
5.在C中,除非显示地初始化自动变量,不然它不会被自动初始化。
6. void trystat() {
int fade = 1;
static int stay = 1;
}
这两个声明看起来很类似,可是第一个语句确实是函数trystat()的一部分,每次调用该函数都会执行它,它是个运行时动做,而第二个语句实际上并非函数的一部分。静态变量和外部变量在程序调入内存时已经就位了,把这个语句放在函数内部是为了告诉编译器只有函数trystat()能够看到该变量,它不是在运行时执行的语句。
7. 外部变量
1)把变量的定义声明放在全部函数以外,即建立了一个外部变量。
2)在使用外部变量的函数中经过使用extern关键字来再次声明它
3)若是变量实在别的文件中定义的(而不只仅是在文件头部定义的话),使用extern来声明一下该变量就是必须的。
8. 定义和声明的区别
int tern = 1;
main()
{
external int tern;
...
}
这里tern声明了两次。第一次声明为变量留出了存储空间,构成了变量的定义,称为定义声明
第二次声明只是告诉编译器要使用先前定义的变量tern,所以不是一个定义,为引用声明,关键字extern代表该声明不是一个定义。
9. 一个外部变量只能够进行一次初始化,并且必定是在变量被定义时进行。下面的语句是错误的
extern char permis = 'Y';
10.具备内部连接的静态变量
普通的外部变量能够被程序的任一文件所包含的程序使用,而具备内部连接的静态变量只能够被与它在同一个文件中的函数使用。能够在函数中使用存储类说明符extern来再次声明任何具备文件做用域的变量。这样的声明并不改变连接。
11.除了一个定义声明外,其余全部声明都必须使用关键字extern,而且只有在定义声明中才能够对该变量进行初始化。
12. 函数能够是外部的,静态的或者内联的。与变量相似。
12.将头文件文件名置于双引号而不是非尖括号中,是为了只是编译器在本地寻找文件,而不是到编译器存放标准头文件的标准位置去寻找文件。一些常见的作法是将头文件与源代码文件放在同一个目录或文件夹中,或者与工程文件放在同一个目录或文件夹中。
13.stdlib.h里包括的函数原型:rand(), malloc(),free(),exit()
14.free()只释放它的参数所指向的内存块,若是free()在一个程序的最后而后立刻退出的话,没有free()也能够,由于在程序终止后全部已经分配的内存都将会被自动释放。
15.一个理想模型:程序将它的可用内存分为三个独立的部分:一个是具备外部连接的,具备内部连接的以及具备空连接的静态变量的部分;一个是自动变量的部分;一个是动态分配的内存的部分:
1)在编译时就已经知道了静态存储时期存储类变量所需的内存数量,存储在这一部分的数据在整个程序运行时均可用。这一类型的每一个变量在程序开始时就已存在,到程序结束时终止。
2)一个自动变量在程序进入包含该变量定义的代码块时产生,在退出这一代码块时终止。所以,伴随程序对函数的调用和终止,自动变量使用的内存数量也在增长和减小。典型的,将这一部份内存处理为一个堆栈。这意味在内存中,新变量在建立时按顺序加入,在消亡时按相反顺序移除。
3)动态分配的内存在调用malloc()或相关函数时产生,在调用free()时释放。由程序员而不是一系列固定的规则控制内存持续时间,所以内存块能够在一个函数中建立,而在另外一个函数中释放。因为这点,动态内存分配所用的内存部分可能变成碎片状,也就是说,在活动的内存块之间散布着未使用的字节片。无论怎样,使用动态内存每每致使进程比使用堆栈慢。
16. restrict关键字告诉编译器某个指针是访问它所指向数据块的惟一初始方式,编译器能够放心去寻找计算的捷径。好比合并两次加法。
17. 从宏变成最终的替换文本的过程称为宏展开
18. C编译器在编译时对全部常量表达式(只包含常量的表达式)求值,因此实际相乘过程发生在编译阶段,而不是预处理阶段。预处理器不进行计算,他只是按照指令进行文字替换操做。
19.对于#include。 使用双引号意味着首先搜索本地目录,可是具体搜索那个目录依赖于编译器,有些编译器搜索源代码文件所在目录,有些则搜索当前工做目录,