《C程序设计语言》总结一

《C程序设计语言》总结一

这段时间正在重新学习C语言,原来就听老师说过K&R,就选择了K&R的《C程序设计语言》;读了一些也记录一下琐碎的东西(个人习惯)。有错误的地方希望大家可以指正。

1. C语言除了静态定义和栈自行分配以外没有定义其他的存储分配方式,没有堆或者垃圾回收(The language does not define any storage allocation facility other than static definition and the stack discipline provided by the local variables of functions;there is no heap or garbage collection)
2. C语言中所有的变量都必须在用之前声明,通常在函数开始处,在所有可执行语句之前。
3. 尽管C编译器不关心一个程序的编程风格是什么样的,适当的缩进和空格会使程序容易读和理解。每行只写一条语句,在操作符两边用空格来表明分类。
4. 如果一个算术运算符有整型操作数,会进行整型操作。如果一个算术运算符有一个浮点操作数和一个整型操作数,那么整型操作数会在操作进行之前转换成浮点数。
5. 在C语言中,任何赋值语句都是一个表达式并且有一个值,整个表达式的值是在赋值完成以后赋值号左边的变量的值。
6. 用两个单引号‘’括起来的字符代表一个整型值,这个整型值与这个字符在机器字符集(machine’s character set)中对应的数值相同,这就是字符常量,其实就是比较小的整数的另一种写法。
7. 用&&和||连接的表达式从左到右求值,并保证在在求值过程中,只要能判断最终结果的真假,求值就会终止。
8. 数组下标可以是任何整型表达式,包括整型变量和整型常量。
9. 根据定义,char只是小一些的整数,所以char类型的变量和常量在算术表达式和int是同样的。
10. 不带有表达式的return语句把控制权交还给调用者,但是没有返回值,就像是程序运行到终止的右括号。
11. 一般常用return 0表示正常终止,非零值表示不正常或错误终止的情况。
12. C语言中所有函数参数都是通过值传递。就是说被调用的函数的参数的值是通过临时变量的方式得到的,而不是主调函数中的原本的变量。
13. C语言中被调用函数不能直接更改主调函数中的值,它只能改变它私有的、临时的拷贝版本。相当于在函数调用中,被调函数会重新在函数体中定义参数变量,它们的值就是主调函数调用被调函数时所用的值。
14. 当数组名被作为参数时,传递的是数组的起始地址,并没有数组元素的拷贝。
15. 局部变量在函数被调用时存在,函数执行完毕退出时消失。
16. 一个外部变量必须定义在所有函数之外,而且在所有的源文件中只能定义一次,在定义时会分配存储空间。
17. 通常把变量和函数的extern声明放到一个单独的文件中(习惯上称头文件),通过#include在每个源文件的最前面包括进来。
18. “定义”指的是变量被创建和分配空间,“声明”指的是说明变量的性质,但并不分配存储空间。
19. 定义变量的时候不要用下划线开头!
20. 传统C语言用法中变量名用小写字母,符号常量全部用大写字母。
21. 不带限定符的char类型对象是有符号的还是无符号的取决于具体的机器,但是可打印的字符都是正数。
22. 整型常量前面带0代表八进制,前面带0x或0X代表十六进制。
23. 一个字符常量的值是它在机器字符集中对应的值。
24. 字符常量可以像其他整型一样参与数值运算,尽管常常用来和其他的字符作比较。
25. ‘\0’经常用来代替0来强调一个表达式的字符特性,其实它实际的值就是0。
26. 常量表达式是只有常量的表达式,这种表达式在编译阶段就可以求值而不是在运行时求值。
27. 一个字符串的内部表示在末尾处有’\0’(空字符),所以一个字符串实际物理上所需要的存储空间比写在双引号之间的多一个。
28. 枚举类型中第一个的值是0,第二个是1,然后依次下去,除非有明确的赋值。
29. 尽管可以声明枚举类型的变量,但是编译器并不检查这种类型变量中存储的值是否为该枚举的有效值。
30. 外部变量和静态变量在默认情况下被初始成0。
31. const可以用于所有变量声明中,表明它的值不能被改变。
32. const也可以用于数组参数中,表明这个函数不能改变这个数组。
33. %不能用于float和double。
34. 算数运算符>关系运算符>逻辑运算符
35. 总体上,唯一的自动转换是那些“narrower”操作数转换成“wider”操作数,这样转换不会丢失信息(比如int转换为char就会丢失前面三个字节的信息)。会丢失信息的转换可能会有警告但完全合法。
36. 在char类型到整型的转换中,因为没有具体定义char类型是有符号的还是无符号的,那么这种转换会产生一个负数吗。答案不确定。(不过我觉得各种编译器应该已经确定了这种情况)
37. 所以为了便于可移植,当非字符型的数据要存储到char类型变量中时,说明是有符号还是无符号。
38. 在一个二元运算符中,如果操作数不同类型,那么在运算进行之前,低类型会转换到高类型。
39. 注意,float并不会自动转换到double。
40. 赋值时,右边的值会自动转换成左边的类型,左边的类型就是结果的类型。
41. 转换规则:有long double转到long double;否则有double转double;否则有float转float;否则把char和short转为int;然后如果有long,把其他转为long。
42. double转为float时是四舍五入还是截取取决于机器。
43. 注意,强制类型转换运算符只是产生一个值为n的合适的类型,n本身并没有改变。
44. 如果有函数原型声明,当函数调用时,自动强制类型转换为参数类型。
45. n++先使用n后对n进行+1,++n先对n进行+1,再使用n的值。
46. 右移一个无符号数空位填0,右移一个有符号数在某些机器上空位补符号位(算术右移),在另一些机器上空位补0(逻辑右移)。
47. 用unsigned修饰保证右移时空位补0。
48. 所有表达式中,赋值表达式的值和类型是赋值以后左操作数的值和类型。
49. 条件表达式expr1 ? expr2 : expr3,实际上也是一个表达式,可以出现在其他任何表达式可以出现的地方。如果expr2和expr3有不同的类型(比如float和int),那么这个表达式就是float类型不管条件判断是什么样。
50. C语言没有明确定义一个操作符的操作数的求值顺序(除了&&,||,?:,’,’这几个操作符)。例如x = f() + g();f和g谁先求不能确定下来。同样的,函数参数中的求值顺序也是不确定的
51. 函数调用,嵌套赋值语句,增量和减量操作会产生副作用,某些变量的改变可能是因为一个表达式的求值产生的副作用。
52. 分隔函数参数,变量声明等等的逗号不是逗号操作符,不保证从左到右求值。
53. break语句导致最内层的循环或switch语句中立刻跳出。
54. continue语句使for、while、或者do循环的下一次迭代立即开始。在while和do中,表示判断部分立即执行,在for语句中,进行增量步骤执行;在for循环中的switch中的continue使for循环开始下一次迭代。
55. 如果函数有参数就声明,没有参数就用void。
56. 任何函数都可以通过变量名引用外部变量,只要以某种方式声明。
57. 外部变量作用域是从它声明的地方开始到被编译文件的末尾。
58. 外部变量的初始化在值在定义时执行。
59. 到某种程度的程序,只需要一个头文件包含所有的东西。再大一点的或可以考虑更多的头文件。
60. static静态修饰符:①修饰外部变量或者函数的时候,表明这个变量或者函数的作用域只有在它们定义的这个文件当中;②修饰内部变量的时候,为一个函数提供私有的永久的存储空间。(不再是当函数被调用时存在,执行完毕退出后消失)
61. 在没有明确的初始化的情况下,外部变量和静态变量保证被初始化为0。自动变量和寄存器变量没有定义初始值。对于外部变量和静态变量,必须用常量表达式初始化。
62. 通常用明确的赋值,在声明时初始化不便于阅读程序。
63. 在初始数组时,提供的值比数组元素个数少的时候,剩下的自动初始为0。不能一次将一个初始化表达式指定给多个数组元素,也不能跳过前面的数组元素而直接初始化后面的数组元素。
64. #include中用”“包含,就先从程序所在的文件查找头文件,如果没有找到,再按定义的路径查找;用<>包含就按照定义的路径查找。
65. 可以定义带参数的宏替换,那么在不同的宏调用中替换的文本也就不同。例如#define max(A, B) ((A) > (B) ? (A) : (B))看起来像是函数调用,但是用max会扩展成内置代码。
66. 上面的表达式其实被求值了两次,如果包含有副作用的表达式,会出现错误。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章