《C专家编程》7-8章阅读收获

来源:互联网 发布:妈妈讲故事软件 编辑:程序博客网 时间:2024/05/17 23:00

第7章   对内存的思考


在Inter80X86内存模型,段是内存模型设计的结构。在X86结构中,各处理器的地址空间并不一致,
(因为要保持兼容性),但它们都被分割为以64KB为单位的区域,这些被称为段。
段地址        +       偏移地址         =        最终地址A0000                  FFFF                         AFFFF

虚拟内存
SunOS的进程执行于32位地址空间。操作系统负责具体细节,使得每个进程都以为自己拥有独立的地址
空间的独家访问权。而这个幻觉就是就是通过虚拟内存实现的。
所有进程共享机器的物理内存,当内存用完就用磁盘保存数据。
进程运行时,数据在内存和磁盘之间来回移动。
内存管理硬件(MMU)负责把虚拟地址翻译为物理地址,并让一个进程是始终运行与系统的真正内存中。
应用程序程序员只看得到虚拟地址。虚拟地址内存通过“页”的形式组织。页是指在操作系统在磁盘和内存中
移来移去或者进行保护的单位。
当进程不会马上运行的时候(优先级低或者处于睡眠等状态的时候),操作系统暂时取回所有分配内存,将其备份到磁盘(交换区)。
操作系统内核将常驻与物理内存中。
进程只能操作位于物理内存中的页。当进程引用一个不在物理内存(即处于磁盘中)的页时。内存管理单元MMU会产生一个页错误。

数据段和堆
数据段使用堆(heap)完成了自动增长需要。
具体是采用三种动态内存申请方式,调用malloc()、calloc()、realloc() 等库函数。calloc和malloc类似,但它在返回指针之前先把分配好的
内存的内容都清空为零。realloc函数改变一个指针所指向的内存块的大小,既可以将其扩大,也可以把它缩小。

~释放或改写仍在使用的内存,称为内存损坏。
~未释放不再使用的内存,称为内存泄漏。

总线错误:几乎都是由未对齐的读或者写引起的。
段错误:内存管理单位MMU异常 包括以下的行为:
1、对一个包含非法值的指针解除引用。
2、对一个空指针解除引用。
3、未得到正确权限进行访问
4、用完堆栈空间。

第8章 隐式类型转换


在等待时类型发生了变化
当操作符的操作数类型不一致的时候发生类型转换,以便进行运算。这称为“寻常算术转换”。
然而,类型转换不仅仅发生在这个地方,在涉及类型小于int或者double的表达式中,都可能出现类型转换。
以下面的代码为例子:
printf("%d",sizeof'A');
输出结果并不是1,而是4。char类型在表达式中类型提升为int,所有它的长度为4。
在表达式中,每个char都被转换为int...注意所有位于表达式中的float都被转换为double。

这个特性被称为“类型提升”

C语言中的类型提升

源类型通常提升后的类型charint位段(bit-field)int枚举(enum)intunsigned charintshortintunsigned shortintfloatdouble任何数组相应类型的指针
在K&R C中,函数参数是表达式,所以会发生隐式类型转换
在ANSI C中,使用函数原型,则可以避免隐式类型转换

********************************************************************************************************

printf()格式化字符串%d为什么能使用几种不同类型?

%d格式化字符串short、char、int都能适配。因为不管是上述哪种的参数,函数从堆栈中(或者寄存器中)
取出的参数总是int类型,并在printf或其他被调用函数里按统一格式处理。如果用%d打印比int长的类型如long long int
,将会出现错误。除非使用 long long 的格式化限定符%ld。

*******************************************************************************************************
在ANSI C中建立了函数原型,消除了实参和形参因为隐式类型提升所造成的类型不匹配。

那么,为什么要建立隐式类型提升的机制(先提升为更大的类型,然后裁剪为原来的类型)
是为了简化编译器,把所有操作数转换为统一的长度极大地简化了代码的生成。

原型可能失败的地方:
·K&R C函数声明和K&R C的函数定义        顺利调用,传递的参数会进行类型提升
·ANSI C函数声明和ANSI C的函数定义      顺利调用,传递的参数为实际参数
·ANSI C函数声明和K&R C的函数定义       可能失败!
·K&R C函数声明和ANSI C的函数定义        可能失败!

用C语言实现有限状态机(FSM)

C语言中有好几种方法实现FSM,其中绝大多数使用函数指针数组
void (*state[MAX_STATES])();
如果知道函数名,就可以像下面这样对数组进行初始化。
extern int a(),b(),c(),d();int (*state[])() = { a, b, c, d };

可以使用数组中的指针来调用函数
(*state[i]) ();
state[i] ();

(***************state[i]) ()/*甚至是这种非主流写法*/

强制类型转换

强制类型转换一般有2个方面的应用:
一是类型转换,如下代码所示:
(float) 3;
二是消除类型歧义
(float) 3.0;

在C中经典排序库函数qsort(),就是通过强制类型转换调用的。
qsort()的声明:
void qsort(void base,size_t nel ,size_t width, int (*compar) (const void* , const void*));
当调用qsort()函数时,可以向它传递一个你喜欢的比较函数,该函数将接收实际的数据类型而非void*   
int intcompare(const int *i, const int *j){    return (*i-*j)}
但是intcompare的参数并不与compar()的参数完全匹配,所以进行强制类型转换。
具体调用方式如下所示:
qsort(    a,    10,    sizeof(int);    (int (*) (const *void, const *void) ) intcompare);








原创粉丝点击