再读《C专家编程》

《C专家编程》和《C和指针》《C陷阱与缺陷》这两本书一起是我三四年前买的,现在已不记得当初看第一遍时的感想。现在准备一个C语言考试,不禁想起了这几本书。既然要考就顺便把C认真复习一下。以前总是对C有一种排斥感,第一是那本据称“销量1000万册”的某某C教材竟然教丑陋的TurboC的IDE使我大为失望;二是不觉得C很强大,感觉C是个轻量级的语言。三四年以后,我已不是还会去讨论“C、C++和Java到底哪个更好”的年龄。尤其是接触了Linux和GCC后,使我感到C的很强的硬件相关性,并且能使我更好的理解编译后端和计算机体系结构。

一、编译过程

一般来说编译过程可以划分为四个部分:

1.预处理

预处理的功能有三个:1.字符串替换;2.头文件包含;3.宏扩展处理。预处理把.c文件转换成.i文件。通过命令gcc -E hello.c可以看到打印预处理后的结果。这时完成的结果还是C语言。

2.编译

编译过程也有三个阶段:1.语法和语义分析;2.代码生成器;3.优化器。编译过程把.i文件转换成.s文件。通过命令gcc -S hello.c可以生成hello.s文件。这是完成的结果是汇编语言。

3.汇编

汇编过程把.s文件转换成.o文件。通过命令gcc -c hello.c可以生成hello.o文件。这个文件成为目标文件。

4.链接

链接过程是把.o文件链接成可执行文件。这个阶段是错误最多的阶段。链接分为静态链接和动态链接。动态链接又有与位置无关方式(通过环境变量决定?)和由运行时链接器安排代码(缺省,有文件系统路径决定?)

二、内存分配

看到很多编程的书都讲了内存分配,但都讲的不完整。在这初步总结下Linux下的内存分配。

+---------------+------------------------------

|  内核虚拟内存 |内核地址区

+---------------+------------------------------

|    用户栈     | 用户地址区

|      |        |

|      V        |

+---------------+

|               |

+---------------+----------

|     数据     |共享库映射区

+---------------+

|     文本      |

+---------------+

|     ...       |

+---------------+

|     数据      |

+---------------+

|     文本      |

+---------------+----------

|      ^        |

|      |        |

|   运行时堆    |

+---------------+

|     BSS       |

|     数据      |

+---------------+

|     文本      |

+---------------+0x08048000(32bit)

|               |

+---------------+------------------------------

三、数组与指针

1.在外部声明时(如extern char a[];),数组是数组,指针是指针,不能混用。

2.在定义时(如char a[10];另注:定义会申请空间,所以需要具体的数组元素个数),数组是数组,指针是指针,不能混用。

3.在做参数传递时(如func(char a[]);另注:也许是数组拷贝元素太多和数组名本身没有空间),可自由选择数组和指针,因为数组会被编译器转换成指针。

4.在做表达式计算时(如c=a[i];另注:此处或c=*(a+i);),可自由选择数组和指针,因为数组会被编译器转换成指向数组第一个元素的指针。

发表评论