einpoklum
einpoklum

Reputation: 131519

Do _Complex types in C99 behave like std::complex<> in C++?

I've recently noticed the existence of types for complex values in C99 (after noticing their construction macros as a feature of C11).

Since this is C, these are built-in types, not structs with overloaded operators etc. But - is it or is it not the case that I can treat them as though they were based on C++'s std::complex template? i..e. is float _Complex effectively the same as std::complex<float> and double _Complex the same as std::complex<double>?

Note: Of course they have exactly the same behavior, since C++ has features which C doesn't, but think of it as though we restrict ourselves to the "C subset" except for these two types.

If they are not effectively the same - please explain how they differ.

Upvotes: 2

Views: 1124

Answers (1)

user1143634
user1143634

Reputation:

std::complex is different from _Complex mainly in its interface.

To get real part of std::complex you use constexpr T real() const member function, the same for _Complex types requires creal macro.

So they are not the same type and it will be hard to pretend they are, but they do have the same internal layout.

C++17 29.5.4 states:

If z is an lvalue expression of type cv complex then:

  • the expression reinterpret_cast<cv T(&)[2]>(z) shall be well-formed,
  • reinterpret_cast<cv T(&)[2]>(z)[0] shall designate the real part of z, and
  • reinterpret_cast<cv T(&)[2]>(z)[1] shall designate the imaginary part of z.

Moreover, if a is an expression of type cv complex<T>* and the expression a[i] is well-defined for an integer expression i, then:

  • reinterpret_cast<cv T*>(a)[2*i] shall designate the real part of a[i], and
  • reinterpret_cast<cv T*>(a)[2*i + 1] shall designate the imaginary part of a[i].

And C18 6.2.5.13 states:

Each complex type has the same representation and alignment requirements as an array type containing exactly two elements of the corresponding real type; the first element is equal to the real part, and the second element to the imaginary part, of the complex number.

Which means you can use std::complex<T> and _Complex T to write interoperable code for C and C++.

Note: _Complex was introduced in C99.

Upvotes: 5

Related Questions