C++ 不支持的 C 元素


C++ 不支持的 C 元素

文章插图
 
C 是用于开发系统软件和任何微处理器软件的经典语言 。linux,大部分windows和macOS都是写在上面的 。如果你使用任何现代可穿戴小工具或电子设备,在大多数情况下它们也会在 C 程序的控制下运行 。世界上有大量的代码是用 C 语言编写的,而且还会有更多 。
C++ 是那些同时需要 C 的所有功能和面向对象编程的灵活性的人的选择 。Counter-Strike、StarCraft 和 World of Warcraft 是用 C++ 编写的,这意味着您可以将 C 的性能与现代技术相结合 。Unity 引擎的一部分也是用 C++ 编写的,以直接访问系统内存和资源 。
简单描述一下这些语言的区别,C++是C的改进版 。这些语言99%的语法和命令都是一样的,只是C更多的是结构化和过程化编程,而C++是面向对象的 。
在本文中,我将分享一个 C 代码示例列表,这些示例不是 C++ 正确的或表现出某些 C 特定行为 。请注意,它是一个方向:C 代码,从 C++ 的角度来看,这是不正确的 。
当然,C 语言与 C++ 语言有许多显着差异,任何人都不难举出基于关键字或其他明显的 C99 独有特性的不兼容示例 。您不会在此列表中找到它 。我选择示例的主要标准是,对于 C++ 观察者来说,代码在第一眼看来应该足够“无辜”(即,不包含明显的 C 独占代码),但仍然是特定于 C 语言的 。
*对于 [C23],我将标记与 C23 发布无关的项目 。
26 元素列表1.在C中,在用字符串文字初始化字符数组时允许“丢失”尾随的:
char s[4] = "1234";在 C++ 中,这样的初始化是不正确的 。
2. C 支持暂定义 。在一个翻译单元中,您可以在没有初始化器的情况下对同一对象进行多个外部定义:
int a;int a;int a, a, a;C++ 中不允许这样的多重定义 。
3. C 语言允许定义不完整类型的外部对象,前提是该类型在同一翻译单元的某个地方被重新定义并变得完整:
struct S s; struct S { int i; };在基本原理层面,这种可能性很可能只是前一段的结果,即支持暂定定义 。从 C++ 的角度来看,上述声明顺序是不正确的:C++ 语言立即禁止定义不完整类型的对象 .
4. 在C 中,可以使不完整类型的非定义实体声明为void 。
extern void v;但是在C中不能做相应的定义,因为void是一个不完整的类型 。在C++中,你甚至不能做非定义声明 。
5. C 语言允许使用 const 限定符定义变量而无需显式初始化:
void foo(void){const int a;}在 C++ 中,这样的定义是不正确的 。
6. C 语言允许在 cast 运算符、sizeof 运算符和函数声明(返回类型和参数类型)中声明新类型:
int a = sizeof(enum E { A, B, C }) + (enum X { D, E, F }) 0;/* 下面的代码使用上面的声明 */enum E e = B; int b = e + F;C++ 中不允许这样的声明 。
7. 在 C 中,函数参数列表中提到的“不熟悉的”结构类型名称是该函数本地新类型的声明 。同时,在函数参数列表中,可以将此类型声明为不完整的,对函数体中已有的完整类型进行“追加声明”:
void foo(struct S *p){struct S { int a; }s;p = &s;p->a = 5;}在这段代码中,从 C 语言的角度来看,一切都是正确的:p 与 &s 具有相同的类型,并且包含字段 a 。
从 C++ 语言的角度来看,在函数参数列表中提到一个“陌生”的类类型名称也是一种新类型的声明 。然而,这个新类型不是本地的:它被认为属于封闭的命名空间 。因此,从C++语言的角度来看,函数体中类型S的局部定义与参数列表中提到的类型S无关 。由于类型不匹配,分配 p = &s 是不可能的 。从 C++ 的角度来看,上面的代码是不正确的 。
8. C 语言允许将控制转移到“跳过”其初始化声明的自动变量的范围:
switch (1){int a = 42;case 1:;}从 C++ 的角度来看,这种控制转移是不允许的 。
9. 自C99 以来,C 语言中出现了隐式块:一些语句本身就是块,此外,还引入了嵌套的子块 。例如,for 循环本身就是一个块,循环体是嵌套在 for 循环块中的一个单独的块 。因此,下面的代码在 C 中是合法的:
for (int i = 0; i < 10; ++i){int i = 42; }在循环体中声明的变量 i 与在循环头中声明的变量 i 无关 。
在 C++ 语言中,在这种情况下,循环头和循环体都形成一个单一的作用域,这就排除了 i 的“嵌套”声明的可能性 。


推荐阅读