C陷阱与缺陷--读书笔记6 预处理器
摘要:第六章一、知识点1、getchar和putchar经常被实现为宏,以避免在每次执行输入或者输出一个字符这样简单的操作时,都要调用相应的函数而造成系统效率的下降。(P100)2、宏只是对程序的文本起作用,宏提供了一种对组成C程序的字符进行变换的方式,而并不作用于程序中的对象。(P101)3、对于宏定义:(P101)#define f (x) ((x) - 1)f(x) 代表的是(x) ((x) - 1)。这是因为 f 和后面的(x)之间多了一个空格,如果希望定义f(x) 为 ((x) - 1),必须这样写:#define f(x) ((x) - 1)这一规则不适用于宏调用,而只对宏定义适用。因此
阅读全文
posted @
2012-05-01 09:24
谷堆旁边
阅读(506)
推荐(0)
C陷阱与缺陷--读书笔记5 库函数
摘要:第五章一、知识点1、对于一个例子:#include <stdio.h>main(){ char c; while((c = getchar()) !=EOF) putchar(c);}getchar函数在一般情况下返回的是标准输入文件中的下一个字符,当没有输入时返回EOF。这依程序乍一看似乎是把标准输入复制到标准输,实则不然。原因在于程序中的变量c被声明为char型,而不是int类型。这意味着c无法容下所有可能的字符,特别是,可能无法容下EOF。(P92)2、更新顺序文件:(P93)3、C语言实现通常都允许程序员进行实际的写操作之前控制产生的输出数量。这种控制能力一般通过库函数se
阅读全文
posted @
2012-05-01 09:23
谷堆旁边
阅读(497)
推荐(0)
C陷阱与缺陷--读书笔记3 语义“陷阱”
摘要:第三章一、知识点1、C语言中的数组值得注意的地方有以下两点:(P41)(1)、C语言中只有一维数组,而且数组的大小必须在编译期就作为一个常数确定下来。然而,C语言中数组的元素可以是任何类型的对象,当然也可以是另外打的一个数组。(2)、对于一个数组,我们只能够做两件事:确定该数组的大小,以及获得指向该数组下标为0的元素的指针。其他有关数组的操作,哪怕它们乍看上去十一数组下标进行运算的,实际上都是通过指针进行的。换句话说,任何一个数组下标运算都等同于一个对应的指针运算,因此我们完全可以依据指针行为定义数组下标的行为。2、对于int calendar[12][31]; 这个语句生命了calendar
阅读全文
posted @
2012-05-01 09:19
谷堆旁边
阅读(365)
推荐(1)
C陷阱与缺陷--读书笔记4 连接
摘要:第四章一、知识点1、典型的连接器把由编译器或汇编器生成的若干个目标模块,整合成一个被称为载入模块或可执行文件的实体,该实体能够被操作系统直接执行。(P74)2、连接器通常把目标模块看成是由一组外部对象组成的。每个外部对象代表着机器内存中的某个部分,并通过一个外部名称来识别。因此,程序中的每个函数和每个外部变量,如果没有被声明为static,就都是一个外部对象。除了外部对象之外,目标模块还可能包括了对其他模块中的外部对象的引用。当连接器生成载入模块的过程中,它必须同时记录这些外部对象的引用。当连接器读入一个目标模块时,它必须解析出这个目标模块中定义的所有外部对象的引用,并作出标记说明这些外部对象
阅读全文
posted @
2012-05-01 09:19
谷堆旁边
阅读(196)
推荐(0)
C陷阱与缺陷--读书笔记2 语法“陷阱”
摘要:第二章一、知识点1、函数运算符()的优先级高于单目运算符*。(P26)2、我们一旦知道了如何声明一个变量,也就自然知道如何对一个常数进行类型转换,将其转型为该变量的类型:只要在变量声明中将变量名去掉即可。(P27)例如:fp是一个指向返回值为void类型的函数的指针,那么(*fp)()的值为void,fp的声明为:void (*fp)();将常数0转型为“指向返回值为void的函数的指针”类型,可以这样写:(void (*)()) 03、关于操作符优先级:(P30)(1)、优先级最高者并不是真正意义上的运算符,包括:数组下标、函数调用操作符、各结构成员选择操作符。它们都是自左向右结合;(2)、
阅读全文
posted @
2012-05-01 09:18
谷堆旁边
阅读(302)
推荐(0)
C陷阱与缺陷--读书笔记1 词法“陷阱”
摘要:第一章一、知识点1、术语“符号”(token)指的是程序的一个基本组成单元。(P15)2、除了字符串与字符常量,符号的中间不能嵌有空白(空格符、制表符、换行符)。例如:下面的表达式:a---b与表达式a -- - b的含义相同,而与a - -- b的含义不同。(P19)3、在C语言中,用单引号引起的一个字符实际上代表一个整数,整数值对应于该字符在编译器采用的字符集中的序列值。用双引号引起的字符串,代表的却是一个指向无名数组起始字符的指针,该数组被双引号之间的字符以及一个额外的二进制值为零的字符‘\0’初始化。(P21)4、a+++++b唯一有意义的解释是a++ + ++b,但它也有可能被理解为
阅读全文
posted @
2012-05-01 09:17
谷堆旁边
阅读(328)
推荐(0)
C专家编程--读书笔记十一 你懂得C,所以C++不在话下
摘要:第十一章一、知识点1、面向对象的关键就是把一些数据和对这些数据进行操作的代码组合在一起,并用某种手法将它们做成一个单元。面向对象编程的特点是继承和动态绑定。C++ 通过类的派生支持继承,通过虚拟函数支持动态绑定。虚拟函数提供了一种封装类体系实现细节的方法。(P247)2、面向对象编程的关键概念:(P248)(1)、类:类是一种用户定义类型,就好像是int这样的内置类型一样。内置类型已经有了一套完善的针对它的操作(如算术运算等),类机制也必须允许程序员规定他所定义的类能够进行的操作。类里面的任何东西被称作类的成员。(2)、对象:某个类的一个特定变量,就像j可能是int类型的一个变量一样,对象也可
阅读全文
posted @
2012-05-01 09:15
谷堆旁边
阅读(341)
推荐(0)
C专家编程--读书笔记十 再论指针
摘要:第十章一、知识点1、C标准规定%s说明符的参数必须是一个指向字符数组的指针。所以如:char *p = NULL;printf("%s", p);这是不正确的。NULL是一个指针,但它并不指向一个字符数组。(P236)2、在C语言中,数组是静态的,数组的长度在编译时已确定不变:(P237)3、在C语言中实现动态数组:(P239)二、问题1、编写一个main()程序,使用上面提到的那个函数。检查一下原先的数组,并填充足够的元素,使之调用realloc()函数进行扩张。(P241)
阅读全文
posted @
2012-05-01 00:17
谷堆旁边
阅读(180)
推荐(0)
C专家编程--读书笔记九 再论数组
摘要:第九章一、知识点1、所有作为函数参数的数组名总是可以通过编译器转换成指针。然而,数组和指针在编译器处理时是不同的,在运行时的表示形式也是不一样的,并可能产生不同的代码。对编译器而言,一个数组就是一个地址,一个指针就是一个地址的地址。(P205)2、什么时候数组和指针是相同的?(P207)(1)、表达式中的数组名(与声明不同)被编译器当作一个指向该数组第一个元素的指针;(2)、下标总是与指针的偏移量相同;(3)、在函数参数的声明中,数组名被编译器当作指向该数组第一个元素的指针。3、在C语言中,所有非数组形式的数据实参均以传值形式(对实参作一份拷贝并传递给调用的函数,函数不能修改作为实参的实际变量
阅读全文
posted @
2012-04-30 23:26
谷堆旁边
阅读(290)
推荐(0)
C专家编程--读书笔记八 为什么程序员无法分清万圣节和圣诞节
摘要:第八章一、知识点1、图标或者图形,是一种小型的位模式映射于屏幕产生的图像。一个位代表图像上的一个像素。如果一个位被设置,那么它所代表的像素就是“亮”的。(P175)2、在C语言中,字符常量的类型是int,而在C++中它们的类型是char。例如:printf("%d", sizeof 'A');这行代码的输出结果是4,即int的长度;而如果在.cpp文件中输入这段代码,则结果为1,即char的长度。(P177)3、值得警惕的地方是参数也会被提升。在函数的参数传递时会发生隐式类型转换。在K&R C中,由于函数的参数也是表达式,所以也会发生类型提升。在AN
阅读全文
posted @
2012-04-30 23:24
谷堆旁边
阅读(409)
推荐(0)
C专家编程--读书笔记七 对内存的思考
摘要:第七章一、知识点1、作为80x86内存模型最基本的形式,8086中的段是一块64K的内存区域,由一个段寄存器所指向。内存地址的形成经过是:取得段寄存器的值,左移4位(相当于乘上16),或者换中思路,把段寄存器的值看成是20位的,也就是在值得右边扩充4个0。然后就是16位的偏移地址,它表示段内的地址。如果把段寄存器的值(经过移位)加上偏移地址,就得到最终的地址。不同的段地址加上偏移地址所形成的值可能指向同一个内存地址。(P146)2、讨论数字概念时,需要注意所有的磁盘制造商都是使用十进制数而不是二进制数来表示的磁盘的容量。所以2GB的磁盘可以存储2000000000个字节的数据而不是214748
阅读全文
posted @
2012-04-30 23:20
谷堆旁边
阅读(406)
推荐(0)
C专家编程--读书笔记六 运行时数据结构
摘要:第六章一、知识点1、代码和数据的区别也可以认为是编译时和运行时的分界线。编译器的绝大部分工作都跟翻译代码有关;必要的数据存储管理的绝大部分都在运行时进行。(P121)2、"a.out"是“assembler output(汇编程序输出)”的缩写形式。(P121)3、就目标文件而言,段(segments)是二进制文件中简单的区域,里面保存了和某种特定类型(如符号表条目)相关的所有信息。一个段一般包含几个section。段表示一个二进制文件相关的内容块。(P122)4、一个可执行文件一般包含三个段:文本段、数据段、bss段(由符号开始的块)。BSS段只保存没有值得变量,所以事实
阅读全文
posted @
2012-04-30 23:18
谷堆旁边
阅读(370)
推荐(0)
C专家编程--读书笔记五 对链接的思考
摘要:第五章一、知识点1、动态链接可以从两个方面提高性能:(1)、动态链接可执行文件比相同功能的静态链接可执行文件的体积小。它能够节省磁盘空间和虚拟内存,因为函数库只有在需要时才被映射到进程中。(2)、所有动态链接到某个特定函数库的可执行文件在运行时共享该函数库的一个单独拷贝。操作系统内核保证映射到内存中的函数库可以被所有使用它们的进程共享。这就提供了更好的I/O和交换空间利用率,节省了物理内存,从而提高了系统的整体性能。如果可执行文件是静态链接的,每个文件都将拥有一份函数库的拷贝,显然这极为浪费。(P100)2、使用函数库时的5个基本的约定:(P103)(1)、动态库文件的扩展名是“.so”,而静
阅读全文
posted @
2012-04-30 23:16
谷堆旁边
阅读(165)
推荐(0)
C专家编程--读书笔记四 数组和指针并不相同
摘要:第四章一、知识点1、C语言中的对象必须有且只有一个定义,但它可以有多个extern声明。定义是一种特殊的声明,它只能出现在一个地方,确定对象的类型并分配内存,用于创建新的对象;而声明可以多次出现,描述对象的类型,用于指代其他地方定义的对象(例如在其他文件里)例:extern int my_array[];extern对象告诉编译器对象的类型和名字,对象的内存分配则在别处进行。由于并未在声明中为数组分配内存,所以不需要提供关于数组长度的信息。对于多位数组,需要提供除最左边一维之外其他维的长度。(P88)2、编译器为每个变量分配一个地址(左值)。这个地址在编译时可知,而且该变量在运行时一直保存于这
阅读全文
posted @
2012-04-30 23:11
谷堆旁边
阅读(290)
推荐(0)
C专家编程--读书笔记三 分析C语言的声明
摘要:第三章一、知识点1、涉及指针和const的声明可能会出现几种不同的顺序:(P62)const int * grape;int const * grape;int * const grape_jelly;在最后一种情况下,指针是只读的,而在另外两种情况下,指针所指向的对象是只读的。当然对象和指针有可能都是只读的,下面两种声明方法都能做到这一点:const int * const grape_jam;int const * const grape_jam;2、合法的声明中:函数的返回值不能是一个函数,所以像foo()()这样是非法的;函数的返回值不能是一个数组,所以像foo()[]这样是非法的;数
阅读全文
posted @
2012-04-30 23:10
谷堆旁边
阅读(2)
推荐(0)
C专家编程--读书笔记二 这不是bug,而是语言特性
摘要:第二章一、知识点1、C语言中,无论何时遇到这样一条语句malloc(strlen(str));,几乎可以断定它是错误的,而malloc(strlen(str)+1)才是正确的。这是因为其他的字符串处理库函数几乎都包含一个额外空间,用于容纳字符串结尾的‘\0’字符。所以,人们很容易忽略strlen这个特殊情况。(P33)2、一个'L'的NUL用于结束一个ACSII字符串,ACSII字符中零的位模式被称为‘NUL’;两个'L'的NULL用于表示什么也不指向(空指针)。这两个术语不可互换。(P34)3、switch语句中关键字case的后面跟着的是常量值或者常量表达式
阅读全文
posted @
2012-04-30 23:06
谷堆旁边
阅读(2)
推荐(0)
C专家编程--读书笔记一 穿越时空的迷雾
摘要:第一章一、问题1、auto的意思是“在进入程序块时自动进行内存分配”(与全局静态分配或在对上动态分配相反),了解一下各种变量以及数据在内存或者堆上的分配。(P9)2、关于const的相关使用?二、知识点1、C预处理器的功能:(P10)(1)、字符串替换:形式类似“把所有的foo替换为baz”,通常用于为常量提供一个符号名;(2)、头文件包含:一般性的声明可以被分离到头文件中,并且可以被许多源文件使用;(3)、通用代码模板的扩展:与函数不同,宏在连续几个调用中所接受的参数的类型可以不同(宏的实际参数只是按照原样输出)。在宏的扩展中,空格会对扩展的结果造成很大的影响。2、long int 的最大值
阅读全文
posted @
2012-04-30 23:01
谷堆旁边
阅读(2)
推荐(0)