【问题标题】:C++11 complex<float>* to C float complex*C++11 complex<float>* 到 C float complex*
【发布时间】:2018-11-29 23:49:42
【问题描述】:

我在 C++11 中使用了一组复杂的浮点数:

std::complex<float> *cx;

我正在尝试使用一个较旧的库,它采用 C 风格的复杂浮点数:

float complex *cx;

当我尝试这个时:

std::complex<float> *cpp = new std::complex<float>[100];
complex float *c = reinterpret_cast<complex float*>(cpp);
c_process(c); // c_process(complex float *c)    [ c library function ]

我明白了:

error: expected ';' before 'float'   
complex float *c = reinterpret_cast<complex float*>(cpp);
        ^

问题是 C 库的标头包含 #include &lt;complex.h&gt;,而我的 C++11 代码中有 #include &lt;complex&gt;,它使用 std::complex。

来自&lt;complex&gt;class complex 和来自&lt;complex.h&gt;#define complex _Complex 似乎在complex 这个词上发生冲突。

一种解决方案: 此解决方案仅在您可以修改其他库的标头时才有效。

由于权限关闭这个问题(虽然我认为这是一个很好的),这就是我所做的:

由于&lt;complex.h&gt; 有一个#define complex _Complex 并且&lt;complex&gt; 包含一个class complex,因此包含两个标头时会出现一些冲突。

我不得不在我的代码和其他库的头文件中将所有float complex* 更改为float _Complex*。这从 cstyle 的定义和 c++ 样式的类复合体中消除了单词 complex 的冲突,而不改变代码的作用。

【问题讨论】:

  • "我什么都试过了"——那么向我们展示你的尝试应该很容易。
  • 本网站的规则明确规定我们不是作业网站。您应该在minimal reproducible example 中向我们展示您已经尝试做些什么来解决您的问题。发布您正在使用的两种类型的定义不满足该要求。此外,您的问题仍然不清楚:在这种情况下,“在它们之间移动”是什么意思?是什么阻止您使用基本函数将 std::complex&lt;float&gt; 数组转换为 _Complex 数组?
  • 我已经澄清了我的问题 Xirema。还是想不通。
  • I punched your code into an online compiler,并收到一条不同的错误消息,与 complex 关键字未映射到有效类型有关。用_Complex 交换complex 消除了编译错误。我不知道您使用的是哪个编译器,但您的编译器似乎不会像文档建议的那样将 _Complex 别名为 complex
  • 您不必修改其他库的标题。您只需要做两件事:1.在包含所述库后立即添加#undef complex(可能包含在#ifdef/#endif中)2.按照您所说的,将complex float替换为_Complex float你自己的 C++ 代码。

标签: c++ c


【解决方案1】:

这种不兼容只是语法,两种语言都保证它们的复杂类型与float[2](或double[2]等)具有相同的布局。因此,您可以在两者之间进行调解,以使用根据扩展语言定义的宏 cfloat。类似于

#ifdef __cplusplus
typedef std::complex<float> cfloat;
#else
typedef float _Complex cfloat;
#endif

然后在你所有的函数原型中使用这个cfloat

【讨论】:

  • @Xirema C++ 已对 std::complex 进行了特定豁免,以实现与 C 的二进制兼容性。
  • @NathanOliver 注意。答案可能应该在相关文本中添加参考以验证:en.cppreference.com/w/cpp/numeric/complex
  • 这是什么cfloat?我试图在互联网上搜索它,但失败了。还有什么比简单的投射更方便的吗?
【解决方案2】:

这可能很容易。 std::complex 定义了复杂对象的存储顺序,并提供了访问复杂对象数组的实部和虚部的方法。如果顺序与您旧图书馆中的顺序相同,那么您可能很幸运

来自http://en.cppreference.com/w/cpp/numeric/complex

对于complex&lt;T&gt; 类型的任何对象zreinterpret_cast&lt;T(&amp;)[2]&gt;(z)[0]z 的实部,reinterpret_cast&lt;T(&amp;)[2]&gt;(z)[1]z 的虚部

对于指向名为pcomplex&lt;T&gt; 数组元素的任何指针和任何有效的数组索引ireinterpret_cast&lt;T*&gt;(p)[2*i] 是复数p[i] 的实部,reinterpret_cast&lt;T*&gt;(p)[2*i + 1] 是复数的虚部p[i]

因此您可以简单地参考兼容C99的float _Complex *cx

`std::complex *cx1 = reinterpret_cast*> cx;

由于同时包含complexcomplex.h 时发生冲突,一种方法是从 C 标头中提取基本声明,并将其与使用的 C 函数声明一起包含在“C”extern 语句中,如下所示:

#include <iostream>
#include <complex>

extern "C" {
    // this is commented out because it is also declared in the c++ complex header
    //typedef struct _C_float_complex
    //{ /* float complex */
    //    float _Val[2];
    //} _C_float_complex;
    typedef _C_float_complex _Fcomplex;
void double_my_reals(_Fcomplex *pcx, int len);
}


int main()
{
    std::complex<float> cf[5]{ 1,2,3,4,5 };
    for (auto x:cf)
        std::cout << x << std::endl;
    double_my_reals(reinterpret_cast<_Fcomplex*>(cf), 5);
    for (auto x:cf)
        std::cout << x << std::endl;
}

此代码特定于 Visual Studio C 和 C++。 VSC 与 C99 不兼容,但数据结构相同,因此您需要在任何 C 编译器中提取复杂浮点数的特定声明。

这将是 VC 调用的“C”代码示例。

#include <complex.h>

void double_my_reals(_Fcomplex *pcx, int len)
{
    for (int i = 0; i < len; i++)
    {
        pcx[i]._Val[0] *= 2.0f;
    }
}

【讨论】:

  • 我试过这个。请查看我的编辑。我的标题发生冲突,因为我在使用的库中遇到了一些语法错误。库头文件强制我包含 并且我必须在我的 C++11 代码中包含 。我认为问题是我必须两者兼得。
  • 在您的原始帖子中,您说您的旧 C 库使用 _Complex,这就是 C 的工作方式,现在您已将其更改为 complex,这将与未定义发生冲突。如果没有更完整的示例,很难提供帮助。
  • 看看这个:stackoverflow.com/questions/23414270/… 它涉及在同一个翻译单元中使用 的必要机制。特别是complex&lt;complex.h&gt; 中定义的宏之间的冲突
  • 道格,感谢您的链接。这提供了一些的清晰度。问题是我正在使用的库的头文件中的函数。它们都使用“float complex*”,因此“#undef complex”会导致这些函数的编译错误。
猜你喜欢
  • 1970-01-01
  • 2018-05-26
  • 2013-05-22
  • 1970-01-01
  • 1970-01-01
  • 2011-07-11
  • 1970-01-01
  • 1970-01-01
  • 2022-01-10
相关资源
最近更新 更多