11

以下代码在 C 中编译并运行得很好(至少根据 'gcc -std=gnu99'),但在 C++ 下编译失败,给出“第 5 行:错误:无法将 'double' 转换为 'double complex ' in初始化”。有人知道为什么吗?

#include "/usr/include/complex.h"
#include <stdio.h>

int main(int argc, char * argv[]) {
  double complex a = 3;  // ERROR ON THIS LINE
  printf("%lf\n", creal(a));
  return 0;
}

我意识到在 C++ 中还有另一种处理复数的方法,但我必须在 C++ 中使用 C 复数,因为这就是我得到的遗留代码的作用方式。谢谢,如果你能帮忙!

4

3 回答 3

19

C++ 编译器可以选择支持_Complex关键字作为扩展(少数支持),但这不是可移植的。如果您想拥有一个可移植的 C++ 解决方案,那么不幸的是,您需要使用 C++ std::complex 模板。

好消息是 C++ std::complex numbers 保证与 C complex numbers 兼容(从某种意义上说,指向一个的指针总是可以转换为指向另一个的指针,并且会发生正确的事情),这意味着如果您需要与需要 C 复杂值的 C 库进行互操作,您将不会遇到任何麻烦。

C11:

每个复杂类型具有与恰好包含对应实类型的两个元素的数组类型相同的表示和对齐要求;第一个元素等于复数的实部,第二个元素等于复数的虚部。

C++11:

如果z是 cv 类型的左值表达式,std::complex<T>则:

— 表达式reinterpret_cast<cv T(&)[2]>(z)应格式正确,

reinterpret_cast<cv T(&)[2]>(z)[0]应指定 的实部z,并且

reinterpret_cast<cv T(&)[2]>(z)[1]应指定 的虚部z

于 2012-05-10T18:44:17.863 回答
10

使用 C 关键字表示复杂:_Complex。C++ 使用 complex 作为(模板)类。我不确定 creal 在哪里,否则我会取消注释。

#include <complex.h>
#include <cstdio>

int main(int argc, char * argv[]) {
  double _Complex a = 3.0 + 0.0I;  // DECLARATION WORKS NOW - NOTE ASSIGNMENT MUST HAVE IMAG PART
  //printf("%lf\n", creal(a));
  return 0;
}

这适用于 gcc(我用 g++ 编译)。我收到有关已弃用的 .h 标头的警告。

是一个电子邮件跟踪的链接,显示了与 C++ 和 C 的非标准兼容性以及复数。C++11 要求 C++ 复合体与 C _Complexes 的布局兼容性。

我目前正在研究 C++ 中的 creal 等。我在标准中找不到任何东西。由于似乎有一些努力在 C++ 和 C 之间提供一些源代码兼容性,因此 creal、cpow 等可能会对 TR2 库提案做出很好的补充。

于 2012-05-10T18:41:21.393 回答
9

C 和 C++ 的兼容性

C++ 不支持 C99 的一些添加或与 C++ 功能冲突,例如可变参数宏、复合文字、指定的初始值设定项、可变长度数组和本机复数类型。C99 中定义的 long long int 数据类型和限制限定符不包含在当前的 C++ 标准中,但一些编译器(例如 GNU Compiler Collection[4])将它们作为扩展提供。新的 C++ 标准 C++11 中包含 long long 数据类型以及可变参数模板,通过这些模板可以实现可变参数宏的某些功能。另一方面,C99 通过合并 C++ 特性(例如 // 注释以及混合声明和代码)减少了其他一些不兼容性。

于 2012-05-10T18:40:06.137 回答