"这篇文档是关于C语言常见问题的集合,由Steve Summit原著,并由朱群英和孙云翻译。内容涵盖了声明与初始化、结构、联合和枚举等多个主题,旨在帮助读者深入理解和掌握C语言的精髓。"
C语言是编程的基础之一,尤其在系统编程和底层开发中占有重要地位。以下将详细介绍标题和描述中涉及的部分知识点:
1. **声明和初始化**
- **整数类型选择**:C语言提供了多种整数类型(如`int`, `short`, `long`, `long long`),选择哪种类型取决于你需要存储的数值范围以及平台的位宽。在64位系统上,`long`通常为64位,但并非总是如此,应根据实际需求选择。
- **全局变量和函数声明**:全局变量在整个程序中可见,而函数声明用于告诉编译器函数的存在,通常放在头文件中供其他源文件引用。
- **extern关键字**:在函数声明前使用`extern`表示该函数定义在其他文件中,提示编译器在链接阶段寻找函数的定义。
- **auto关键字**:在局部变量声明时使用,但在现代C语言中,`auto`通常是默认的,其作用已经不那么重要。
2. **函数和指针**
- **复杂声明理解**:理解复杂的声明需要从右向左读取,例如,一个指向返回字符指针的函数的指针数组的声明,应先找到最内层的类型,然后向外扩展。
- **main()函数定义**:标准C规定,`main()`函数可以是`int main(void)`或`int main(int argc, char *argv[])`的形式,`void main()`是不标准的,可能导致不兼容问题。
- **未初始化变量**:未初始化的全局变量通常会获得不确定的初始值,不应依赖其默认为零。局部变量则未定义,使用前必须初始化。
- **动态内存分配**:`malloc()`分配的内存需要初始化,如`char *p = malloc(10); p[0] = 'H';`,否则访问未初始化的内存是危险的。
- **字符串和字符数组**:`char a[] = "stringliteral";`是字符串字面量的副本,可修改;`char *p = "stringliteral";`是只读的,尝试修改会导致未定义行为。
- **函数指针初始化**:声明并初始化函数指针如`int (*func_ptr)(int) = my_function;`,其中`my_function`是函数名。
3. **结构、联合和枚举**
- **结构体声明**:`struct x1 {}`定义结构类型,`typedef struct {} x2;`创建别名,两者不同但可以相互转换。
- **匿名结构**:`struct x {int a;}; x the_x;`是正确的,而`struct x {}; x the_x;`是错误的,因为`x`没有名字。
- **自引用结构**:结构可以包含指向自身的指针,这是实现递归数据结构(如链表)的关键。
- **抽象数据类型**:通过定义私有结构和提供公共接口,可以实现C语言中的抽象数据类型。
- **面向对象特性**:C语言本身并不支持面向对象编程,但可以通过模拟(如结构体嵌套函数指针)来实现类似功能。
4. **结构体的特殊用法**
- **结构体大小调整**:`struct name {int namelen; char namestr[1];}`这种结构体常用于动态字符串,`namestr[1]`留作对齐和扩展的空间。
这些知识点构成了C语言学习的基础,理解和掌握它们能帮助开发者编写出高效、可靠的C语言程序。继续深入学习和实践,可以解决更复杂的编程问题。