首页 电脑 电脑学堂 查看内容

一些容易混淆的 C 和 C++ 的不兼容特性

2016-6-21 12:11 1670 0

摘要: C 和 C++ 是两种不同的编程语言, 特别的, C 并不是 C++ 的子集。 但二者又高度相关。 C++ 自诞生以来, 一直以能够兼容C作为自己的目标之一。 在两种语言的不断演化中, C 和 C++ 都互相从对方身上吸收了不少内容 ...

C 和 C++ 是两种不同的编程语言, 特别的, C 并不是 C++ 的子集。 但二者又高度相关。 C++ 自诞生以来, 一直以能够兼容C作为自己的目标之一。 在两种语言的不断演化中, C 和 C++ 都互相从对方身上吸收了不少内容。 举个例子, C99 标准开始支持 C++ 风格的//注释, C++11 标准支持 C99 的 long long 整型, 等等。

C 和 C++ 的不兼容大致可以分为三个方面:

  1. C++ 支持而 C 不支持的功能
  2. C 支持而 C++ 不支持的功能
  3. C 和 C++ 都支持, 但语法/语意细节不同的功能

第一类非常多, 比如各类 OOP 功能, template 功能。 第二类在 C99 推出时也有不少, 但随着 C++11 的推出, 很多 C99 引入的特性也被加入 C++ 了。 而第三类, 是本文的重点, 因为这类特性是最容易混淆的。

以下讨论仅针对标准的 C/C++, 不包括各种编译器扩展。

const修饰符

C 和 C++ 都有一个重要的概念, 叫做常量表达式(constant expression), 特点是可以在编译时就得到值, 而不需要运行时。 有些语法要求只能使用常量表达式, 比如数组的长度, case 语句的表达式, 等等。

那么, const 变量是否可以用作常量表达式呢? 答案在 C 和 C++ 中并不一样, 比如下面这段代码:

在 C++ 中, 这段代码是合法的, 因为 N 可以当做常量 100 一样使用。 (在 C++11 中, 这里还可以用 constexpr)。 但在 C89 中, 这段代码是非法的, 因为即使变量声明为const, 它仍然不是常量表达式。

但可能有人会问, 我试过这段代码, 可以编译的啊。 那是因为, C99中支持可变长度数组(variable length array, 经常缩写为VLA), arr 这里被解析为一个VLA, 所以虽然这段代码在 C99 中变成合法的, 但 arr 仍然不是一个普通的(固定长度的)数组, 因为 N 仍然不是常量表达式。

void *指针

void *指针在 C 语言中用作通用指针。 C++ 虽然仍然支持它, 但由于有更强大的泛型编程, void *的用处要少很多。

作为通用指针, void * 可以和其他任意类型的指针相互转换, 但要注意, C 语言中这种类型转换是隐式的(implicit conversion), 而在 C++ 中必须有显式的类型转换(explicit conversion)。

看下面的代码:

指针a的初始化在 C 语言中是合法的, 而在 C++ 中是非法的。 指针 b 的初始化在 C/C++ 中都是合法的。

这也是 C++ 比 C 的类型系统更强的一个例子。

思考题: malloc的返回值需要做类型转换吗? 也就是说:

最新评论