如何在 C 中分配复数变量的实部和虚部

How to assign real and imaginary parts of complex variables in C

使用C99标准的复数类型,如何分别给一个变量的实部和虚部赋值?我发现 GNU 扩展 __real__ 和 __imag__ 将执行此操作,如以下示例程序所示。但这不是便携式或标准的。如何便携地做到这一点?

#include <stdio.h>
#include <stdlib.h>
#include <complex.h>

int
main()
{
  complex double z;

  __real__ z = 3.0;
  __imag__ z = 2.0;

  fprintf(stderr, "z = %f + i %f\n", creal(z), cimag(z));

  return 0;
}

How can one do this portably?

只是...补充:

z = 3.0;
z += I * 2.0;

你可以先将虚部归零,如果你想:

z = creal(z) + I * 2.0;

how does one assign the real and imaginary parts of a variable individually?

// assign real
z = new_value + I * cimag(z);
// assign imaginary 
z = creal(z) + I * new_value;

人们可能更喜欢 _Imaginary_I CMPLXF 宏而不是 I

我找到了另一种可能的解决方案。下面的代码假定复数 double 与 double[2] 位等效(我认为这是正确的,但希望得到验证!)。我认为下面的解决方案可能更有效,因为它不涉及每个分配的额外加法操作(就像 KamilCuk 的解决方案一样)。

如果有人可以验证这是否适用于所有平台,我将不胜感激。

#include <stdio.h>
#include <stdlib.h>
#include <complex.h>

#define SET_REAL(z, x) ( *((double *) &(z)) = (x) )
#define SET_IMAG(z, x) ( *(((double *) &(z)) + 1) = (x) )

int
main()
{
  complex double z;

  SET_REAL(z, 3.0);
  SET_IMAG(z, 2.0);

  fprintf(stderr, "z = %f + i %f\n", creal(z), cimag(z));

  return 0;
}

C 2018 6.2.5 13 表示我们可以将复数视为包含两个元素的数组:

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.

这是粗略的措辞,与 6.5 7 中明确规定的别名规则不一致,但该标准并不完善,关于整数和指针的脚注 41 和 49 建议此类关于表示和对齐的陈述应该允许尽管有 6.5 中的规则,但仍将对象的一种视图用于另一种视图 7. 如果是这样,我们可以定义宏:

#define Re(x)   (_Generic((x), \
    complex float       : ((float *)       &(x)), \
    complex double      : ((double *)      &(x)), \
    complex long double : ((long double *) &(x)))[0])

#define Im(x)   (_Generic((x), \
    complex float       : ((float *)       &(x)), \
    complex double      : ((double *)      &(x)), \
    complex long double : ((long double *) &(x)))[1])

之后 Re(x)Im(x),当给定一个复杂的对象时,产生实部或虚部的左值。所以我们可以分配它们:

Re(x) = 3;
Im(x) = 4;