将双精度数组重新解释为 std::complex<double> 的数组
reinterpreting array of doubles as array of std::complex<double>
虽然 C++11 标准说明了将 std::complex<double>
重新解释为 double
s:
For any pointer to an element of an array of complex<T>
named p
and
any valid array index i
, reinterpret_cast<T*>(p)[2*i]
is the real part
of the complex number p[i]
, and reinterpret_cast<T*>(p)[2*i + 1]
is
the imaginary part of the complex number p[i]
The intent of this requirement is to preserve binary compatibility
between the C++ library complex number types and the C language
complex number types (and arrays thereof), which have an identical
object representation requirement.
逆向重译是真的吗?我的意思是执行这样的操作是否安全:std::complex<double> *cppComplexArray = reinterpret_cast<std::complex<double> *>(cDoublesArray)
where cDoublesArray
have a type of double *
and even length 2 * n
?如果它的长度是奇数 (2 * n + 1
),潜在的陷阱是什么?
在实践中,鉴于前向重新解释强加的强约束(参见 cppreference,std::complex
,实施说明),大多数时候后向重新解释可能会起作用。
但是,我不完全确定这种向后重新解释在理论上是否总是有效:
- 让我们想象一个复杂库的荒谬和假设的实现,它将维护活动复杂对象的地址列表(例如用于调试目的)。这个(可能是静态的)列表将由复杂的构造函数和析构函数维护。
- 此库中的每个复杂操作都会验证其操作数是否在列表中。
- 虽然正向重新解释可行(复杂对象构造良好,其部分可以用作双打),但反向重新解释不起作用(例如,尽管布局兼容,但您会重新解释复杂的一对双打和如果你对它们执行任何复杂的操作,它将失败,因为复合体没有正确构建,即它的地址不在列表中)。
如前所述,这个复杂的库可能是个愚蠢的想法。但是这样的库可以实现并符合标准规范。这足以证明理论上没有反向保证。
你问题的最后一点更容易回答也更明显,假设我们有一个反向重新解释有效的实现。缺少最后一列将导致访问越界的部分。因此,这将导致 UB。
其他阅读材料:标准委员会的 working paper 要求一个通用的可转换性功能,该功能将概括 reinterpret_cast
的行为complex
其他类型。它解释了第 4 节中的复杂情况,以及如果复杂本身不是由数组实现的,编译器需要进行特殊处理才能使其正常工作。
Is it true for the backward reinterpreting? I mean is it safe to perform something like this: std::complex<double> *cppComplexArray = reinterpret_cast<std::complex<double> *>(cDoublesArray)
Casting/initialization 本身是安全的,使用结果就好像指向 std::complex<double>
数组的元素是不安全的。
当cDoublesArray
(或应用于它的数组到指针的转换,如果cDoublesArray
表示一个double
s的数组)points到第一个double
数组的元素,reinterpret_cast<std::complex<double>*>(cDoublesArray)
做同样的事情(具有相同的值)。
在指针算术(例如cppComplexArray + 0
) 会违反 [expr.add]/6:
For addition or subtraction, if the expressions P
or Q
have type “pointer to cv T
”, where T
and the array element type are not similar, the behavior is undefined.
(T
是std::complex<double>
,这里的数组元素类型是double
,不是similar)
虽然 C++11 标准说明了将 std::complex<double>
重新解释为 double
s:
For any pointer to an element of an array of
complex<T>
namedp
and any valid array indexi
,reinterpret_cast<T*>(p)[2*i]
is the real part of the complex numberp[i]
, andreinterpret_cast<T*>(p)[2*i + 1]
is the imaginary part of the complex numberp[i]
The intent of this requirement is to preserve binary compatibility between the C++ library complex number types and the C language complex number types (and arrays thereof), which have an identical object representation requirement.
逆向重译是真的吗?我的意思是执行这样的操作是否安全:std::complex<double> *cppComplexArray = reinterpret_cast<std::complex<double> *>(cDoublesArray)
where cDoublesArray
have a type of double *
and even length 2 * n
?如果它的长度是奇数 (2 * n + 1
),潜在的陷阱是什么?
在实践中,鉴于前向重新解释强加的强约束(参见 cppreference,std::complex
,实施说明),大多数时候后向重新解释可能会起作用。
但是,我不完全确定这种向后重新解释在理论上是否总是有效:
- 让我们想象一个复杂库的荒谬和假设的实现,它将维护活动复杂对象的地址列表(例如用于调试目的)。这个(可能是静态的)列表将由复杂的构造函数和析构函数维护。
- 此库中的每个复杂操作都会验证其操作数是否在列表中。
- 虽然正向重新解释可行(复杂对象构造良好,其部分可以用作双打),但反向重新解释不起作用(例如,尽管布局兼容,但您会重新解释复杂的一对双打和如果你对它们执行任何复杂的操作,它将失败,因为复合体没有正确构建,即它的地址不在列表中)。
如前所述,这个复杂的库可能是个愚蠢的想法。但是这样的库可以实现并符合标准规范。这足以证明理论上没有反向保证。
你问题的最后一点更容易回答也更明显,假设我们有一个反向重新解释有效的实现。缺少最后一列将导致访问越界的部分。因此,这将导致 UB。
其他阅读材料:标准委员会的 working paper 要求一个通用的可转换性功能,该功能将概括 reinterpret_cast
的行为complex
其他类型。它解释了第 4 节中的复杂情况,以及如果复杂本身不是由数组实现的,编译器需要进行特殊处理才能使其正常工作。
Is it true for the backward reinterpreting? I mean is it safe to perform something like this:
std::complex<double> *cppComplexArray = reinterpret_cast<std::complex<double> *>(cDoublesArray)
Casting/initialization 本身是安全的,使用结果就好像指向 std::complex<double>
数组的元素是不安全的。
当cDoublesArray
(或应用于它的数组到指针的转换,如果cDoublesArray
表示一个double
s的数组)points到第一个double
数组的元素,reinterpret_cast<std::complex<double>*>(cDoublesArray)
做同样的事情(具有相同的值)。
在指针算术(例如cppComplexArray + 0
) 会违反 [expr.add]/6:
For addition or subtraction, if the expressions
P
orQ
have type “pointer to cvT
”, whereT
and the array element type are not similar, the behavior is undefined.
(T
是std::complex<double>
,这里的数组元素类型是double
,不是similar)