读书笔记之:C语言核心技术

第1章 C语言基础
1. 概念
 C是很小的内核语言,并包含极少的硬件相关元素,可以说具有相当高的可移植性。比方说,C语言不提供有关文件操作或动态内存管理等语句。事实上,甚至不直接提供控制台输出和输入语句。C语言的做法是是使用扩充的标准C链接库,为各式各样的编程目的提供各种所需的函数。
 因为C是专门作为“系统编程”而开发的,它目前主要的用途之一就是编写”嵌入式系统程序“,这一点不会让我们感到惊讶。许多开发者把C当作可移植的,结构化的高级程序语言,以编写诸如文字处理器、数据库以及图形应用程序。
第7章 函数
一个源文件就是一个翻译单元。前面说过#include指令只是将文件的内容插入到#include指令的位置,比如这样的代码也是可以的:#include "mydoc.txt"或者#include "mycsource.c"但是这样写出的代码有点怪异,所以这里我们按照一般的概念,编译源文件(.c文件),#include头文件(.h文件)。确切的说,一个翻译单元就是一个源文件和它include的头文件。一个翻译单元编译成一个目标文件,最后将多个翻译单元连接起来生成一个完整的可执行程序。
1. inline函数
和其他函数不同的是,翻译单元只要用到某个inline函数,就必须重复定义此inline函数,编译器必须准备好此函数,以便插入inline的程序代码,因此,inline函数定义经常被写入在头文件中。
如果翻译单元内的某个函数的所有声明都具有inline修饰符,而没有extern修饰符,那么此函数是inline的。inline定义特别针对翻译单元,它不构成外部的定义,因此别的翻译单元可以包含此函数的外部定义。如果有外部定义附加到inline定义中,那么编译器可以只有选择要使用哪一种定义。
如果使用存储类修饰符extern来声明一个被定义成inline的函数,那么此函数的定义就会是外部的(external)。
然而从别的翻译单元调用函数,将不会被编译成inline。inline函数其实就是一般的函数,只不过在机器码中被调用的方式不同。和一般的函数一样,inline函数具有自己的地址。如果inline函数使用到宏,此处也是展开宏。然而,在没有被声明为static的inline函数,你不应该以静态生存周期的方式来定义可修改的对象。

2. 可选性自变量
这是C语言中对于具有可变参数的函数的支持。
具体要使用这些可变的参数的时候,必须通过一个类型为va_list的对象,它包含了这些参数。该类型定义在stdarg.h中。
可以使用stdarg.h中的4个宏来处理这个指针。
void va_start(va_list argptr,lasparam)
type va_arg(va_list argptr,type)
void va_end(va_list argptr)
void va_copy(va_list dest,va_list src)

第11章 声明
1. 外部链接
具有外部链接的标识符,表示整个程序内部都是相同的函数或对象。编译器会将这种标识符交给连接器(linker),由连接器解析(resolve)这类标识符,并且把其他翻译单元和链接库中的相同标识符链接起来。
在声明函数和对象标识符的时候,如果使用extern存储类型修饰符,那么就具有外部链接。唯一例外的是:如果标识符已经被声明为内部链接,在第一声明的作用域内做第二次声明,并无法将此标识符的链接编程外部链接。

第12章 动态内存管理
二叉搜索树实现及应用

第13章 输入输出
1. C常用标准输入输出函数
C语言输入输出函数有很多,标准I/O函数中包含了如下几个常用的函数:
(1)格式化输入输出
    scanf, fscanf, sscanf
    printf,fprintf,sprintf
    这几个比较简单,也经常用,格式化输入输出。
(2)字符输入输出
    int getc(FILE*fp)   ,int fgetc(FILE*fp)
    从文件中读入一个字符,返回值就是读入的字符,如果错误返回EOF。
    上面的两个函数具有相同的效果,但是getc是宏,而fgetc是函数。程序员常用这个宏,因为它比调用函数更快。
    int putc(int c,FILE*fp),int fputc(int c,FILE*fp)
    与上面的两个函数类似
(3)也是字符输入输出
    int getchar(void),int putchar(int c)
    这两个也是宏实现,主要是从标准输入输出读取或输出字符。等同于getc(stdin)和putc(c,stdout)
(4)字符串的输入输出
    char *gets(char*buf),char *fgets(char*buf,int n,FILE*fp)
    读入字符串,fgets适合取代gets,因为gets无法限制读取字符的个数。
    fgets从流中读入最多n-1个字符,最后加一个空字符作为字符串结尾标记。如果在读到最大个数的字符之前遇到了一个换行字符或者文件结尾,那么只有目前所读入的字符会被放入到缓冲区中,如果独到换行符'\n',那么此字符也会被放入到缓冲区中。
    int puts(const char*s),int fputs(const char *s,FILE*fp)
(5)二进制文件的输入输出
   size_t fread(void*buffer,size_t size,size_t n,FILE*fp),
   size_t fwrite(const void *buffer,size_t size,size_t n,FILE*fp)

第14章 预处理
1. 在宏内使用宏
在执行自变量代换,以及执行#和##运算之后,预处理器会检查结果中的替代文字,并展开其中的宏。但是,空不可以被递归的展开,如果预处理器在“甲宏”的替换文字遇到“甲宏”的名称,或者在嵌套在“甲宏”内的“乙宏”内遇到了“甲宏”的名称,那么“甲宏”的名称就会无法被展开。

 第16章 函数介绍

 1. 文件访问函数

  2. 文件I/O操作

 

 3. 整数算术函数 
4. 浮点数算术函数

 

 5. 字符函数

 

6. 字符串处理函数

7. 数字转化为字符串函数

 

8.搜索函数

 

9. 内存处理函数

 10. 动态内存管理函数
11. 日期和时间函数

 

 

 

12.和操作系统交互函数

 13. 信号处理函数
 
第18章 GCC编译器
1. 编译
编译器的核心任务是把C程序翻译成机器的汇编语言。(实际上,GCC是一个适合多种CPU架构的编译器,不会把C程序语句直接翻译成目的机器的汇编语言,而是在输入语言和输出的汇编语言之间,利用一个中介语言,称为Register Transfer Language(RTL,寄存器传输语言)。借助这个抽象层,在特定上下文,编译器可以选择更经济的方法完成操作编码。)
GCC一般把汇编语言输出到临时文件,并且在汇编器执行完之后立刻删除。但是可以使用-S选项,让编译器在输出汇编语言之后立刻停止。
2. 汇编
因为每个机器架构都有自己的汇编语言,GCC调用宿主系统(hostsystem)的汇编器,把汇编语言翻译成可执行二进制文件。二进制文件是一个对象文件,包含机器码以执行源文件指定的功能,也包含一个符号表(symbol table),描述源文件中有外部链接的所有对象。
3. 链接
链接器把多个二进制对象文件链接成单一的可执行文件。在链接过程中,必须完成程序中多个模块之间的外部参考,把“参考符号”用对象实际的位置代换。连接器会用到汇编器所提供的符号表。
更进一步,链接器也必须将程序中所用到的C标准链接库内的函数加入到其中。对于链接器来说,链接库不过把许多对象文件放在一个文件中,以方便处理罢了。
4. 独立程序
除链接GCC命令行中说指定的对象文件和链接库文件之外,链接器还必须链接系统专用的启动码(startupcode)程序需要启动码才能被加载,并和操作系统进行交互。这部分程序代码位于标准对象文件crtO.o中,包含可执行文件真正的程序进入点(crt是"Cruntime")在大多数系统之上,GCC也会默认链接crtbegin.o和crtend.o对像文件中的初始化子程序。

  第19章 使用Make创建C程序

 

 

 

 
posted @ 2012-02-27 09:55  Mr.Rico  阅读(2237)  评论(0编辑  收藏  举报