《c primer plus》
1. C的四种标准:
1. c78: k&R
2. c89/90 ansi/iso
3. c99
2. c99遵循C++的惯例:定义语句可以放在语句块的任何地方,但必须在引用或访问它的语句之前.
3. 与变量相关的概念:
变量的定义:指出变量是什么,并会为变量分配内存,这时这个变量的内容在内存中的地址已确定.变量的定义有两种形式:无赋值语句和带赋值语句(初始化语句)两种.不管是否有初始化语句,都会为变量分配内存.如果是无赋值语句的全局变量的定义语句,则初始化为相应的系统默认值.
变量的初始化:为变量赋第一次值,如果该变量存在系统给的默认值初始值,则前面所述的"第一次"值将覆盖之.
变量的赋值:为变量赋值,如果是第一次给变量赋值,则这个赋值过程就叫做变量的初始化.
变量的声明:即是为了说明该变量在某个地方存在,后面的语句和程序可以使用和访问它.声明不是定义,它不会为变量分配内存空间.
4. c的数据结构:
c的基本数据类型:整数(包括char),浮点数
复合类型:结枚联引 指数函
5. C/c++中变量在非定义的所有语句中被使用(访问)时得到的值:
某个具体数据值 数据值的地址
基本数据类型 指针
结枚联 数组
引用 函数
6. 函数:函数名(假设为a)是一个指针变量,它的值是函数所对应的内存块的首地址.在函数原型中,该函数名没有加*号,但它就是指针,如果另一个指针b指向该函数,则b和a的类型是一样的.也即以下两个函数原型中:
void a();
void (*b)();
a和b都是函数指针,尽管b前面多了个*号.调用上面两个函数: a(); b();.
7. c中指针变量在其定义时即存在的赋值语句中非常特殊:它被赋的值是一个指针值.而在其它地方,给它赋值指针值时,其前面无*号,如果要为该指针指向的变量赋值则要加*号(在定义中的赋值语句中指针变量的前面是有*号的,这也就是我想要说的特珠的地方).这其实就是操作符重载:一个符号(这里是*号)在不同的语句或上下文中表示不同的含义,另一个例子是&号:"&"符号用在赋值语句中是得到变量的地址,在作为函数的形参和变量的声明或定义语句中时,它表示引用即变量值的一个变量名(也即别名).同样,*号在定义语句和函数原型中(作为形参)只是表示类型,并不是解引用操作(解引用:获取指针变量所指向的数据对象的值).
8. c中调用函数时的传参只传值,无传引用之说.c++中的有传引用的情况,这实际上相当于给变量起了个别名.引用它(或访问它)时会得到相应的变量值,而不是地址.
9. c/c++与java的不同之一是:结枚联对(类的对象)在作为函数形参时,如果形参名无&号,则和基本数据类型一样是传的变量的值,如类变量名(它的值为一个对象)作为形参时,传入的是值,即对象整块内容的拷贝.而java中的类变量全是指针(在Java中也称引用和对象句柄),所以作为形参时,传的是引用(即指针,注意这里的"引用"和C/C++中的"引用"不是同一概念,实际上它们完全是两回事:c/c++中的引用是变量值的变量名,它的值即是变量的值,这和基本数据类型的变量一样,而java中的引用就是指向对象的指针,它的值是对象的地址).
10. 在c/c++/java中只有c++存在传引用的情况.c/java中函数调用中只传值(尽管在java上将类变量(对象"引用")的传递称为"传引用"),c++中传引用时要在形参变量名前加&号,如不加&号,则表示传的是对应变量的值,如果是指针(指针变量名,函数名,数据名),则传的是指针值:地址;如果是其它类型的变量,则传的是具体的数据值.
11. c89之前的某些编译器只能识别变量名的前8个字符,之后的标准编译器允许变量名长达255个字符.(或更多?)我想说的是:存在这样的变量名长度的限制.这可能会在某些情境中造成麻烦.
12.操作系统和c为通常使用一个或两个下划线作为变量名的开头字符,所以自己定义的变量尽量不要使用一个或两个下划线开头(语法上无错).以免造成别人的因惑.
13. 特列字符:键盘上除26个英文字母键外的所有键产生的可能的英文字符.
14. 大小字:c/c++/java/js/lua/linux/unix中的标识符或文件名都区分大小写.dos/windows中的文件名不区分大小写.
15. 基本数据类型使用11个关键字:
k&r(7种): unsigned,short,int,long,char,float,double
short 可写成short int, long可写成long int, long long可写成long long int
c90加两种: signed,void
c99再加三种: _Bool,_Complex,_Imaginary
16. c/c++浮点数的存储:一位符号位,多位小数位,多位指数位
java浮点数(float)的存储:一位符号位,8位指数位,23位尾数位(小数位)
java浮点数(float)的存储:一位符号位,11位指数位,52位尾数位(小数位)
17. c/c++中int占一个字.c仅保证short不比int更长,long不比int更短.
18. printf: %d,%0,%x分别表示十进制,8进制,16进制 %#o,%#x,%#X分别生成"0","0x"和"0X". %hd,%ud,%ld,%ho对应整数. %Lf(L为long,f表用十进制的浮点数打印),%Le,%La(同%Le,表示指数记数法),注意:使用%d显示float值不会把该float值转换成近似的int值,而是显示垃圾值,同样,例用%f显示int值也不会把该int值转换为浮点值.而且,参数的数目不足和类型不区配所造 成的结果也将随平台不同而不同.并且printf()将输出传凝寒给一个被 称为缓冲区的中介存储区域,只当缓冲区满的时候或者遇到换行符的时候经及需要输入的时候才将缓冲区的内容传给屏幕.这一过程叫刷新缓冲区.另一个方法是例用fflush().
19. 127,32767,21亿,92亿亿 *2得无符号
20. long : l or L ; long long ll or LL , u or U 表示无符号. 例: 5ull, 5ULL
21. c/c++中的char可以是一个字节,也可能是4个字节.
22. 65在ascII中是'A',但并不能保证在其它字符集中也是'A',所以字符直接量应使用字符形式,不要使用数字.
23. 非打印字符可使用转义字符表示,如\n表示换行符.转义字符的另一种表示方法:char a = '\007'; char b = '\0x07' 注意有单引号.
24. char可能是有符号的,也可能是无符号的,可在limits.h(整数限制,浮点数限制:float.h)中查看具体(其中会有INT_MAX宏,CHAR_MAX之类的).可用signed和unsigned修饰char,分别表示有符号和无符号.
25. _Bool true:1;false:0;占一位空间.
26. 可移植的类型:inttypes.h
27. long double:至少比double更精确
28. 浮点数的直接量:可略正号;可略小数点(2E5)或指数部分(19.28),但不能同时没有二者.
29. 浮点运算时float会提升至double运算.
30. c99为表示浮点常量添加了一种十六进制格式表示: 使用前缀0x或0X,接着是16进制数字,然后是p或P(不是e或E),最后是2的指数(而不是10的指数),例: 0xa.1fp10 注意其中的'f'表示16进制15.
31. 字符常量的上溢(inf or infinity)与下溢(0.1234E-10除以10后得0.0123E-10丢失了一位精度称下溢)与NaN
32. float只保证小数点前6位是精确的. float a = 1.23455555555; 可能得到: a==1.2345556789. int b = 3.9; 是合法的,b的值为3(不是四舍五入!是截尾).
33. 字符串直接量即是c风格字符串.它的末尾为'\0',但它不是0,且是非打印字符,它又称为NIL(不是NILL).
34. printf,scanf中%s表示一个字符串.
35. stdio.h string.h
36. sizeof后的小括号对于类型是必需的,对于直接量则是可选的.最好都加括号.
37. printf()和其它任何不使用显式原型 的C函数的所有float参数仍然会自动普查转换成double,故不管是k&R C还是ANSI C,都无需专门的转换说明符来显示float类型.
38. 整数在内存中是以补码表示的: 0到32767代表它们本身,数字32768到65535则代表负数,65535代表-1,65534代表-2,以此类推.因此,-3由65536-3也即65533来表示.
39. 计算机在调用printf函数之前会将参数保存到该函数对应的堆栈中,然后根据变量的类型而非转换说明符把这些值放到堆栈中,每个参数占用其实际类型的空间(float参数会自动转换成double,所以占一个double类型的空间).最后,printf函数读取这些参数时,是换其第一个参数串中的转换说明符去读取的,所以如果说明符和参数的类型不一致,则可能会显示错误的值.
40. 一个长字符串的多行表示:
printf("aaa"
"bbb"); // 注意与java不同,这里没有"+"号.
printf("aa" "a"
"b" "bb"); //此句等同于上句
printf("aaa \
asdfasdfasdf"); //"\"后必须紧跟回车符,然后第二行的字符必须顶格,如果有空格,那么空格也是字符串的一部份了.
41. strlen()不包括字符串末尾的空字符.
42. sizeof()返加size_t,在printf中用"%zd",如果不支持可用%u或%lu.
43. 每一个表达式(操作符和操作数组成,expression)都有一个值,表达式加上分号构成一条语句(statement,一条语句是给计算机下的一个完整的命令或任务). 6+(c=3+8) 是一个合法的表达式(结果为6+11),但一般不要这样写.另外,我们一般将赋值语句的右值作为一个表达式.
44. 多条语句构成一个复合语句或代码块(compound statement或block).
45. 副作用: a = 3; 这个表达式语句将3赋给变量a,这就是副作用!在c看来,任何表达式的计算过程所产生的影响都是副作用,只有(表达式的)结果才是c所关注的目的("a = 3"这个表达式的值为3).
46. 一个顺序点(sequence point)是程序执行中的一点;在该点处,所有的副 作用都 在进入下一步前被 计算.在C中,语句里的分号标志了一个顺序点.任何一个完整 的表达式的结整 也是一个顺序点.一个完整的表达式是这样一个表达式:它不是一个更大的表达式的子表达式.
47.
1. C的四种标准:
1. c78: k&R
2. c89/90 ansi/iso
3. c99
2. c99遵循C++的惯例:定义语句可以放在语句块的任何地方,但必须在引用或访问它的语句之前.
3. 与变量相关的概念:
变量的定义:指出变量是什么,并会为变量分配内存,这时这个变量的内容在内存中的地址已确定.变量的定义有两种形式:无赋值语句和带赋值语句(初始化语句)两种.不管是否有初始化语句,都会为变量分配内存.如果是无赋值语句的全局变量的定义语句,则初始化为相应的系统默认值.
变量的初始化:为变量赋第一次值,如果该变量存在系统给的默认值初始值,则前面所述的"第一次"值将覆盖之.
变量的赋值:为变量赋值,如果是第一次给变量赋值,则这个赋值过程就叫做变量的初始化.
变量的声明:即是为了说明该变量在某个地方存在,后面的语句和程序可以使用和访问它.声明不是定义,它不会为变量分配内存空间.
4. c的数据结构:
c的基本数据类型:整数(包括char),浮点数
复合类型:结枚联引 指数函
5. C/c++中变量在非定义的所有语句中被使用(访问)时得到的值:
某个具体数据值 数据值的地址
基本数据类型 指针
结枚联 数组
引用 函数
6. 函数:函数名(假设为a)是一个指针变量,它的值是函数所对应的内存块的首地址.在函数原型中,该函数名没有加*号,但它就是指针,如果另一个指针b指向该函数,则b和a的类型是一样的.也即以下两个函数原型中:
void a();
void (*b)();
a和b都是函数指针,尽管b前面多了个*号.调用上面两个函数: a(); b();.
7. c中指针变量在其定义时即存在的赋值语句中非常特殊:它被赋的值是一个指针值.而在其它地方,给它赋值指针值时,其前面无*号,如果要为该指针指向的变量赋值则要加*号(在定义中的赋值语句中指针变量的前面是有*号的,这也就是我想要说的特珠的地方).这其实就是操作符重载:一个符号(这里是*号)在不同的语句或上下文中表示不同的含义,另一个例子是&号:"&"符号用在赋值语句中是得到变量的地址,在作为函数的形参和变量的声明或定义语句中时,它表示引用即变量值的一个变量名(也即别名).同样,*号在定义语句和函数原型中(作为形参)只是表示类型,并不是解引用操作(解引用:获取指针变量所指向的数据对象的值).
8. c中调用函数时的传参只传值,无传引用之说.c++中的有传引用的情况,这实际上相当于给变量起了个别名.引用它(或访问它)时会得到相应的变量值,而不是地址.
9. c/c++与java的不同之一是:结枚联对(类的对象)在作为函数形参时,如果形参名无&号,则和基本数据类型一样是传的变量的值,如类变量名(它的值为一个对象)作为形参时,传入的是值,即对象整块内容的拷贝.而java中的类变量全是指针(在Java中也称引用和对象句柄),所以作为形参时,传的是引用(即指针,注意这里的"引用"和C/C++中的"引用"不是同一概念,实际上它们完全是两回事:c/c++中的引用是变量值的变量名,它的值即是变量的值,这和基本数据类型的变量一样,而java中的引用就是指向对象的指针,它的值是对象的地址).
10. 在c/c++/java中只有c++存在传引用的情况.c/java中函数调用中只传值(尽管在java上将类变量(对象"引用")的传递称为"传引用"),c++中传引用时要在形参变量名前加&号,如不加&号,则表示传的是对应变量的值,如果是指针(指针变量名,函数名,数据名),则传的是指针值:地址;如果是其它类型的变量,则传的是具体的数据值.
11. c89之前的某些编译器只能识别变量名的前8个字符,之后的标准编译器允许变量名长达255个字符.(或更多?)我想说的是:存在这样的变量名长度的限制.这可能会在某些情境中造成麻烦.
12.操作系统和c为通常使用一个或两个下划线作为变量名的开头字符,所以自己定义的变量尽量不要使用一个或两个下划线开头(语法上无错).以免造成别人的因惑.
13. 特列字符:键盘上除26个英文字母键外的所有键产生的可能的英文字符.
14. 大小字:c/c++/java/js/lua/linux/unix中的标识符或文件名都区分大小写.dos/windows中的文件名不区分大小写.
15. 基本数据类型使用11个关键字:
k&r(7种): unsigned,short,int,long,char,float,double
short 可写成short int, long可写成long int, long long可写成long long int
c90加两种: signed,void
c99再加三种: _Bool,_Complex,_Imaginary
16. c/c++浮点数的存储:一位符号位,多位小数位,多位指数位
java浮点数(float)的存储:一位符号位,8位指数位,23位尾数位(小数位)
java浮点数(float)的存储:一位符号位,11位指数位,52位尾数位(小数位)
17. c/c++中int占一个字.c仅保证short不比int更长,long不比int更短.
18. printf: %d,%0,%x分别表示十进制,8进制,16进制 %#o,%#x,%#X分别生成"0","0x"和"0X". %hd,%ud,%ld,%ho对应整数. %Lf(L为long,f表用十进制的浮点数打印),%Le,%La(同%Le,表示指数记数法),注意:使用%d显示float值不会把该float值转换成近似的int值,而是显示垃圾值,同样,例用%f显示int值也不会把该int值转换为浮点值.而且,参数的数目不足和类型不区配所造 成的结果也将随平台不同而不同.并且printf()将输出传凝寒给一个被 称为缓冲区的中介存储区域,只当缓冲区满的时候或者遇到换行符的时候经及需要输入的时候才将缓冲区的内容传给屏幕.这一过程叫刷新缓冲区.另一个方法是例用fflush().
19. 127,32767,21亿,92亿亿 *2得无符号
20. long : l or L ; long long ll or LL , u or U 表示无符号. 例: 5ull, 5ULL
21. c/c++中的char可以是一个字节,也可能是4个字节.
22. 65在ascII中是'A',但并不能保证在其它字符集中也是'A',所以字符直接量应使用字符形式,不要使用数字.
23. 非打印字符可使用转义字符表示,如\n表示换行符.转义字符的另一种表示方法:char a = '\007'; char b = '\0x07' 注意有单引号.
24. char可能是有符号的,也可能是无符号的,可在limits.h(整数限制,浮点数限制:float.h)中查看具体(其中会有INT_MAX宏,CHAR_MAX之类的).可用signed和unsigned修饰char,分别表示有符号和无符号.
25. _Bool true:1;false:0;占一位空间.
26. 可移植的类型:inttypes.h
27. long double:至少比double更精确
28. 浮点数的直接量:可略正号;可略小数点(2E5)或指数部分(19.28),但不能同时没有二者.
29. 浮点运算时float会提升至double运算.
30. c99为表示浮点常量添加了一种十六进制格式表示: 使用前缀0x或0X,接着是16进制数字,然后是p或P(不是e或E),最后是2的指数(而不是10的指数),例: 0xa.1fp10 注意其中的'f'表示16进制15.
31. 字符常量的上溢(inf or infinity)与下溢(0.1234E-10除以10后得0.0123E-10丢失了一位精度称下溢)与NaN
32. float只保证小数点前6位是精确的. float a = 1.23455555555; 可能得到: a==1.2345556789. int b = 3.9; 是合法的,b的值为3(不是四舍五入!是截尾).
33. 字符串直接量即是c风格字符串.它的末尾为'\0',但它不是0,且是非打印字符,它又称为NIL(不是NILL).
34. printf,scanf中%s表示一个字符串.
35. stdio.h string.h
36. sizeof后的小括号对于类型是必需的,对于直接量则是可选的.最好都加括号.
37. printf()和其它任何不使用显式原型 的C函数的所有float参数仍然会自动普查转换成double,故不管是k&R C还是ANSI C,都无需专门的转换说明符来显示float类型.
38. 整数在内存中是以补码表示的: 0到32767代表它们本身,数字32768到65535则代表负数,65535代表-1,65534代表-2,以此类推.因此,-3由65536-3也即65533来表示.
39. 计算机在调用printf函数之前会将参数保存到该函数对应的堆栈中,然后根据变量的类型而非转换说明符把这些值放到堆栈中,每个参数占用其实际类型的空间(float参数会自动转换成double,所以占一个double类型的空间).最后,printf函数读取这些参数时,是换其第一个参数串中的转换说明符去读取的,所以如果说明符和参数的类型不一致,则可能会显示错误的值.
40. 一个长字符串的多行表示:
printf("aaa"
"bbb"); // 注意与java不同,这里没有"+"号.
printf("aa" "a"
"b" "bb"); //此句等同于上句
printf("aaa \
asdfasdfasdf"); //"\"后必须紧跟回车符,然后第二行的字符必须顶格,如果有空格,那么空格也是字符串的一部份了.
41. strlen()不包括字符串末尾的空字符.
42. sizeof()返加size_t,在printf中用"%zd",如果不支持可用%u或%lu.
43. 每一个表达式(操作符和操作数组成,expression)都有一个值,表达式加上分号构成一条语句(statement,一条语句是给计算机下的一个完整的命令或任务). 6+(c=3+8) 是一个合法的表达式(结果为6+11),但一般不要这样写.另外,我们一般将赋值语句的右值作为一个表达式.
44. 多条语句构成一个复合语句或代码块(compound statement或block).
45. 副作用: a = 3; 这个表达式语句将3赋给变量a,这就是副作用!在c看来,任何表达式的计算过程所产生的影响都是副作用,只有(表达式的)结果才是c所关注的目的("a = 3"这个表达式的值为3).
46. 一个顺序点(sequence point)是程序执行中的一点;在该点处,所有的副 作用都 在进入下一步前被 计算.在C中,语句里的分号标志了一个顺序点.任何一个完整 的表达式的结整 也是一个顺序点.一个完整的表达式是这样一个表达式:它不是一个更大的表达式的子表达式.
47.