2017-05-23 81 views
2

我的FORTRAN 77码的一部分转化为C++FORTRAN等价于C++语言

DIMENSION ARRAY(513),JRRAY(2,513) 
EQUIVALENCE (ARRAY(1),JRRAY(1,1)) 

这是每个变量名开始与I隐含代码,J,K,L,M,N,O, P隐含地被视为整数类型。因此,在这里我们有一个名为ARRAY的双精度数组和一个名为JRRAY的整型数组。

等价性语句将两个数组的起点指向相同的内存位置。然而,不管怎样,当ARRAY(I)被调用时,这些字节被解释为两个不同的形式,或者当JRRAY(I,J)被调用时(至少我认为会发生什么),这些字节被解释为不同的形式。

C++中是否有类似的方法,其中相同的内存位置可以解释为不同的类型?

或者与FORTRAN中的EQUIVALENCE相同,但是在C++中。

+1

回想一下,在fortran数组中,按列的主要顺序存储,所以'JRRAY(1,X)'和'JRRAY(2,X)'指向'ARRAY(X)'的连续部分。 –

+0

您的意思是对表示的实际重新解释还是自动转换?即如果我将pi存储在'ARRAY'中并从'JRRAY'中读出,我会得到'3'还是与'double'的位模式相对应的数字? – Quentin

+0

@Quentin FORTRAN只是重新解释表示,所以这大概是他想在C++中做的。 – Barmar

回答

5

的类似特征是union

union { 
    double array[513]; 
    int jrray[513][2]; 
} equiv; 

然后,您可以访问equiv.array[i]equiv.jrray[i][j]

但是,请注意,访问联合的另一个成员而不是最后写入的成员会导致C++中的未定义行为。见Unions and type-punning。如果您想要将数据重新解释为不同的数据类型,则应使用reinterpret_cast<>,而不是类型双击。

+0

回想一下FORTRAN是列主要的,所以你必须在jrray中切换尺寸 –

+0

这是UB,所以你应该检查你的实现是否真的支持它。 – Quentin

+2

@Quentin如果你访问的是一位不同于你上次写信的成员,那只有UB。工会自己支持。我已经添加了另一个问题的链接,解释了在C和C++中使用类型双击的问题。 – Barmar

1

C union经常用于此目的,如Barmar的answer。然而,你可以使用类型转换来将浮点数组引用为整型数组。

考虑的array如下声明和定义的jrray

double array[513]; 
int (*jrray)[2] = reinterpret_cast<int (*)[2]>(array); 

我们可以检查该声明的工作原理是在看指数如预期的实例。我们将在jrray[k][1]的位20-30中具有array[k]的指数。

例如,检查,如果我们现在初始化数组的元素

array[0] = 1.23*2; // exponent is 1 
array[1] = 1.23*4; // exponent is 2 
array[2] = 1.23*8; // exponent is 3 

,我们将有

((jrray[0][1] >> 20) & 0x7FF) - 1023 == 1 
((jrray[1][1] >> 20) & 0x7FF) - 1023 == 2 
((jrray[2][1] >> 20) & 0x7FF) - 1023 == 3 

无论哪种方式,这违反了C++严格别名规则,并可能导致未定义的行为。

+2

注意:这与上面的联合技巧一样没有定义,但不同于那个,它不是**,通常是由实现定义的,并且会受到最轻微的干扰。有关示例,请参见[这里](https://godbolt.org/g/2EUDU7)。 – Quentin

+0

@Quentin自OP正在移植FORTRAN代码,其中函数参数可能不是别名,他可能是安全的。 –

+0

这只是一个例子。编译器会高兴地认为这是两个不同的数组,如果它允许它进行更多的优化(就像它在内联函数时所做的那样)。你不能依靠它工作。 – Quentin