"495个C语言问题" 是一本关于C语言编程常见问题的集合,由Steve Summit原著,朱群英和孙云翻译,并在2005年6月23日更新至修订版0.9.4。该资源提供了一个全面的C语言问题索引,旨在帮助学习者和开发者解决他们在编程过程中遇到的各种疑问。
1. 在C语言中,选择整数类型通常取决于你需要存储的数值范围以及对性能的要求。比如,`int`通常是默认的整数类型,适用于大多数情况,而`short`占用更少的空间,适合内存受限的环境。`long`和`long long`则可以表示更大的整数,但占用更多内存。
2. 在64位系统上,`long`和`int`通常都是64位,但具体取决于编译器和平台。为了确保跨平台兼容性,可以使用`stdint.h`头文件中的固定宽度整数类型,如`int32_t`和`int64_t`。
3. 全局变量和函数的最好定义和声明应该遵循最小作用域原则,尽量减少全局作用域的使用,以避免命名冲突和潜在的副作用。函数应在被使用之前进行声明,全局变量则可以在需要的地方声明,但在头文件中 extern 声明,以供其他源文件使用。
4. `extern`关键字用于在函数声明中表明该函数是在其他地方定义的,提醒编译器在链接阶段寻找其定义。
5. `auto`关键字在C99标准之后变得不常用,它用于声明局部变量,但在函数参数列表和复合语句(如循环和switch)中是默认的。
6. 在C语言中,结构体可以包含指向自身的指针,这是创建递归数据结构(如链表)的基础。问题中的错误可能是因为typedef和struct定义的方式不正确,应检查语法是否准确。
7. 解析复杂声明的关键是理解指针、数组和函数的关系,以及它们在声明中的读取顺序。例如,一个指向返回字符指针的函数的指针的数组,应从右向左读取。
8. 如果在不同的作用域中重复定义了函数,编译器会报错。C语言要求每个函数有唯一的定义,且在调用前声明。
9. `main()`函数的正确定义通常是`int main(void)`或`int main(int argc, char *argv[])`,`void main()`在某些编译器中可能不被支持。
10. 未初始化的变量其初始值是不确定的,不能依赖于它们默认为零、空指针或浮点零。全局变量在未明确初始化时,其值可能是随机的。
11. 字符数组`char a[]="Hello,world!";`在声明时会被初始化,而代码无法编译可能是因为字符串字面量与动态内存分配(如`malloc`)的混淆。字符串字面量是常量,不能修改。
12. 初始化`char *p=malloc(10);`的问题在于,`malloc`返回的是未初始化的内存,需要使用`strcpy`或`memcpy`来复制字符串到新分配的内存。
13. `char a[]="stringliteral"`是一个字符数组,可以直接修改;而`char *p="stringliteral"`是字符串字面量的指针,修改会引发未定义行为。尝试修改`p[i]`会导致程序崩溃。
14. 函数指针的声明如`typedef int (*func_ptr)(int)`,初始化可以这样:`func_ptr fp = some_func;`其中`some_func`是函数名。
2.1 `struct x1{}`定义了一个结构类型,`typedef struct {} x2;`创建了一个别名,两者的主要区别在于是否给结构类型命名。
2.2 `struct x{}; x the_struct;`错误是因为结构体类型`x`在声明后立即使用,需要先用`struct`关键字,即`struct x the_struct;`。
2.3 结构体可以包含指向自己的指针,如自引用结构,这在实现数据结构如树和图时非常有用。
2.4 实现抽象数据类型(ADT)通常通过结构体和指向结构体的函数指针,将数据和操作封装起来,以隐藏实现细节。
2.5 C语言不是面向对象的语言,但可以通过结构体和函数指针模拟类的行为,或者使用预处理器宏实现类似继承的效果,但这通常比较复杂且难以维护。
这本书涵盖了C语言中的各种基础和进阶问题,从变量声明、类型选择到结构体、联合和枚举的使用,以及函数指针和内存管理等多个方面,是C语言学习者的宝贵参考资料。