【GNU笔记】【C扩展系列】复数 Complex Numbers
复数 Complex Numbers
ISO C99支持复数的浮点数据类型(complex floating data types),作为扩展,GCC在C90模式和C++中支持它们。GCC 还支持不属于 ISO C99 的复数整数数据类型(complex integer data types)。你可以使用关键字_Complex
来声明复数类型。作为扩展,旧的GNU关键字__complex__
也被支持。
例如,_Complex double x;
声明x
是一个变量,其实部和虚部都是double
类型的。_Complex short int y;
声明y
的实部和虚部都是short int
类型;这不太可能有用,但它表明复数类型集是完整的。
要写一个复数数据类型的常量,可以使用后缀i
或j
(任选其一;它们是等价的)。例如,2.5fi
的类型是_Complex float
,3i
的类型是_Complex int
。这样的常数总是有一个纯虚数值,但你可以通过将一个值加到实常数上来形成任何你喜欢的复数值。这是一个GNU扩展;如果你有一个符合ISO C99的C库(比如GNU C库),并且想构造浮点类型的复数常数,你应该包括<complex.h>
并使用宏I
或_Complex_I
代替。
ISO C++14库也定义了i
后缀,所以包含<complex>
头文件的C++14代码不能使用GNU扩展的i
。后缀j
仍然具有GNU的含义。
GCC 可以处理 _Complex
类型和其他 _Complex
类型之间的隐式和显式转换,如将实部和虚部都转换为标量类型。 GCC 可以处理从标量类型到_Complex
类型的隐式和显式转换,其中虚部将被视为零。 C 前端可以处理从_Complex
类型到标量类型的隐式和显式转换,其中的虚部将被忽略。在C++代码中,这种转换被认为是不正确的,G++ 会出错。
GCC 提供了一个内置函数 __builtin_complex
可以用来构造一个复数值。
GCC 有一些扩展,可以用来提取复数表达式的实部和虚部。请注意,如果 exp 是左值,则这些表达式是左值。 这些表达式的操作数的类型是复数类型,可能会从标量类型提升为复杂类型。例如:__real__ (int)x
等于在进行__real__
之前将其转换为_Complex int
。
Expression | Description |
---|---|
__real__ exp | 提取 exp 的实部。 |
__imag__ exp | 提取 exp 的虚部。 |
对于浮点值,你应该使用 ISO C99 函数,在<complex.h>
中声明,也被 GCC 作为内置函数提供。
Expression | float | double | long double |
---|---|---|---|
__real__ exp | crealf | creal | creall |
__imag__ exp | cimagf | cimag | cimagl |
运算符~
用于复数类型的值时执行复数共轭。这是一个GNU扩展;对于浮点类型的值,你应该使用ISO C99函数conjf
、conj
和conjl
,这些函数在<complex.h>
中声明,也被GCC作为内置函数提供。 请注意,与 __real__
和 __imag__
运算符不同,此运算符不会对复数类型进行隐式转换,因为 ~
已经是普通运算符。
GCC 可以以非连续的方式分配复数的自动变量;甚至有可能实数部分在寄存器中,而虚数部分在堆栈中(或者相反)。只有 DWARF 调试信息格式可以表示这一点,因此建议使用 DWARF。如果你使用的是 stabs 调试信息格式,GCC会将一个非连续的复数变量描述为两个独立的非复数类型的变量。如果变量的实际名称是foo
,则两个虚构变量的名称是foo$real
和foo$imag
。你可以使用你的调试器检查和设置这两个虚构的变量。
-
Built-in Function: type __builtin_complex (real, imag)
内置函数
__builtin_complex
用于实现 ISO C11 宏CMPLXF
、CMPLX
和CMPLXL
。 real 和 imag 必须具有相同的类型,即都是实数二进制浮点类型,并且结果具有对应的复数类型,实部和虚部为 real 和 imag。 与“real + I * imag”不同,即使涉及无穷大、NaN 和负零,这也是有效的。
[参考资料]
本文链接:https://blog.csdn.net/u012028275/article/details/124394880