C 编程/C 的特点
外观
< C 编程
C 是一种高效、简约的语言,它有一些程序员必须注意的特殊之处。为了解决这些问题,有时一个好的解决方案是将另一种语言与 C 结合使用,以获得额外的灵活性和功能,例如 Emacs-LISP 和 C 的组合用于 Emacs。有时可以通过使用保证功能和安全的特殊结构来解决它们,但代价是速度变慢和复杂度增加。然而,大多数情况下,通过实践,C 程序员不会遇到这里提到的问题,并且更喜欢使用一种与通用冯·诺依曼硬件架构紧密匹配的语言。
以下是 ANSI C 中的一些特点(有时也是它的优势),一些小,一些大
- 数组和指针之间缺乏区别
- 最早的 C(大约 1973 年)根本没有数组;现代实现是内存中连续的区域,使用指针算术进行访问(注意:声明的数组不能像指针一样赋值),这避免了使用固定大小声明数组的必要性。但是,这种能力在使用不当的情况下会导致缓冲区溢出错误。
- 数组不存储它们的长度
- 上述特性的一个后果。这意味着程序可能需要在访问数组之前显式地执行边界检查。除非函数被传递一个固定大小的数组,否则它无法发现它被传递的数组的长度:因此,函数必须被传递长度,也许作为单独的变量传递给函数或在结构中传递。因此,大多数实现不提供自动数组边界检查,而手动边界检查容易出错。
- 如果 C(或 C++)程序试图访问超出实际分配内存的数组元素,则会发生缓冲区溢出,通常会使程序崩溃。缓冲区溢出错误也是常见的安全漏洞。许多其他计算机语言提供自动边界检查,因此它们几乎不受此类错误的影响。[1][2][3][4][5]
- 可变长度数组
- VLA ‒ 可变长度数组 ‒ 只能用于函数参数和自动变量。VLA 不能在结构体内部使用(除非作为结构体的最后一个项目)。不可能定义一个对应于标准 Forth 字典定义(它有两个可变长度部分)的结构,除非作为
char
的未区分数组。
- 内置的 2D 或 3D 数组的大小不受限制
- 此功能已从 C99 规范开始添加,用于可变长度数组,尽管许多 C 编译器仍然不支持它。如果没有 VLA,函数无法接受任意大小的 2D 或 3D 数组。特别是,不可能定义一个接受
int a[5][4][3];
在一次调用中,并在以后调用中接受int b[10][10][10];
。而不是使用内置的 2D 或 3D 数组数据类型,C 程序员使用其他数据类型来保存(数学)任意大小的 2D 或 3D 数组(多维数组) - 请参见 C 编程/常见做法#动态多维数组 了解详细信息。
- 没有正式的字符串数据类型
- 字符串是字符数组(缺乏任何抽象),并继承了它们的所有约束(结构可以在一定程度上提供抽象)。
- 类型安全性较弱
- C 的类型安全性不是很高。内存管理函数在无类型指针上操作,没有内置的运行时类型强制,并且可以通过指针和强制转换来绕过类型系统。此外,typedef 不会创建新类型,而只是创建别名,因此它仅用于代码可读性。但是,可以使用单成员结构来强制类型安全性。
- 没有垃圾回收
- 作为一种旨在最小化开销的低级语言,C 仅提供手动内存管理,这可能导致简单的内存泄漏不受控制地继续。
- 局部变量在声明时未初始化
- 局部变量(但不是全局变量)必须手动初始化;在此之前,它们包含声明时内存中的任何内容。这并不罕见,但 C 标准并不禁止访问未初始化的变量(这是)。
- 笨拙的函数指针语法
- 函数指针采用
[返回值类型] [名称]([参数 1 类型])([参数 2 类型])
的形式,使得它们难以使用。typedef 可以缓解这种繁重的语法。例如,typedef int fn(int i);
。有关更多详细信息,请参见 C 编程/指针和数组#指向函数的指针。
- 没有反射
- C 程序在运行时无法将字符串评估为源 C 代码语句。
- 嵌套函数不是标准
- 但是,许多 C 编译器确实支持嵌套函数,包括 GNU C。[6]
- 没有正式的异常处理
- 一些标准函数返回特殊值,必须手动处理。例如,
malloc()
在失败时返回 null。例如,必须将getchar()
的返回值存储在int
中(而不是预期的那样,存储在char
中),以便可靠地检测文件结束 - 请参见 EOF 陷阱。不包含适当错误处理的程序在大多数情况下可能运行良好,但在出现异常情况时可能会崩溃或出现其他故障。POSIX 系统通常使用signal()
来处理某些类型的异常。(有关详细信息,请参见 C 编程/错误处理#信号)。一些程序使用setjmp()
、longjmp()
或goto
来手动处理某些类型的异常。(有关详细信息,请参见 C 编程/控制#最后一点:goto 和 C 编程/协程)。
- 没有匿名函数定义
- ↑ http://projects.webappsec.org/Buffer-Overflow
- ↑ http://www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/buffer-overflow.html
- ↑ http://searchsecurity.techtarget.com/news/article/0,289142,sid14_gci860185,00.html
- ↑ http://www.owasp.org/index.php/Buffer_Overflows
- ↑ http://cyclone.thelanguage.org/wiki/Why%20Cyclone
- ↑ "GNU 手册":"C 语言扩展:嵌套函数" [1]