是否可以在c/c++中的double(8字节)类型的变量中存储8个字符(每个1字节)

Is it possible to store 8 characters (1-byte each) in a variable of type double (8-bytes) in c/c++?

本文关键字:类型 变量 存储 1字节 每个 字符 8个 8字节 double 中的 c++      更新时间:2023-10-16

我正在将一些遗留的Fortran77代码迁移到C/C++。在Fortran77代码中,如果从文件中读取8个字符,那么它们可以毫无问题地存储在real*8类型的变量中。

有可能在C或C++中做类似的事情吗?如果是,我该怎么做?我在互联网上找不到任何解决方案。我需要使用C/C++读入8个字符,并将它们存储在double类型的变量中,然后将其传递回Fortran,并对应于原始的实数*8变量。

非常感谢您的帮助。

编辑:作为对@sixlettervariables的回应,我将进一步澄清我的用例。我对他的建议的问题是,我只知道运行时每一行的格式(即哪些字段是字符串,哪些数字(,因此我不知道结构应该静态地具有哪些成员。字段还需要按照读取顺序占用一个连续的内存块

具体地说,在程序的一次运行中,每一行的格式可能是:f1:string,f2:number,f3:number和f4:string,但在另一次f1:string,f2:string和f3:string、f4:number、f5:number中。对于我需要的第一种情况:

struct { char[8] f1; double f2; double f3; char[8] f4}

我需要的第二个:

struct { char[8] f1; char[8] f2; char[8] f3; double f4; double f5} 

也许有一些方法可以用模板做到这一点?

您不需要仅仅因为Fortran需要将它们存储在double中。事实上,您绝对不应该在C/C++代码中这样做。

只需将字符数据存储在字符数组中即可。

如果您将Fortran和C/C++混合在一起,那么除了ABI之外,这两种语言对彼此一无所知。从C端,您可以简单地声明Fortran接口接受一个字符数组,而实际上它需要一个双精度数组。Fortran方面也是如此。

来自C端:

extern void FCHARS(char* str, int length);
/* ... */
int flength = 0; /* optional: length of the string in Fortran terms */
char str[9]; /* in C/C++ add one for  at the end */
/* read in up to a block of 8 */
fgets(str, sizeof(str), fp);
/* At this point if you know the 8 characters are space padded to their end
 * you have no more work to do, otherwise you may need to fill from the right
 * with spaces.
 */
{
    size_t ii = sizeof(str) - 1;
    while (ii > 0 && str[ii - 1] == '') {
        str[ii - 1] = ' ';
        flength = ii--;    /* optional: keep track of our unpadded length */
    }
}
/* Once you've space padded the string you can call your Fortran method.
 * If your Fortran method accepts a string of unknown length, supply
 * `flength`. If your Fortran method expects a string of a fixed length, pass
 * the size of `str` (excluding '') instead.
 */
FCHARS(str, flength);

只要您从C/C++代码中遵循Fortran编译器的ABI要求(例如CDECL,交错传递的隐藏字符串长度(,您就可以了。

当然,只需要使用强制转换。为了安全起见,您可能需要添加一个static_assert:

double d;
char * b = (char*)&d;
static_assert(sizeof(d) == sizeof(char[8]), "Double must be large enough to hold 8 chars");
union Data{
    char c[8];
    double d;
};

将8个字符保存到c中,并通过d读取。示例:

#include <stdio.h>
// #include <stdlib.h>
union Data{
    char c[8];
    double d;
};
int main(){
    int i;
    union Data data;
    for(i = 0; i < 8; i++)
        scanf("%hhd", data.c + i);
    printf("%en", data.d);
    // system("pause");
    return 0;
}

方法1

double a;
char ch;
int i;
for(i=0;i<8;i++)
{
   scanf("%c", &ch);
   a=a+ch;
   if(i!=8)
     a<<8; //left shifts by 8 bits, to accomodate another 8 bits on right.
}

方法2

double a
char *ch;
int i;
ch=&a;
for(i=0;i<8;i++)
{
   scanf("%c", ch);
   ch++;
}

即使在C中可以在DOUBLE变量中存储几个字符和实数,因为C DOUBLE等于real*8,因为两者都是双精度浮点数,我强烈建议不要这样做。

这种在REAL*8中存储几个字符和REAL的"技巧"感觉就像是节省空间的黑客。我认为现在不需要这个了,我也不认为这个"技巧"会产生更快的代码。我建议使用如上所述的UNION。

您可以将FORTAN代码发布到REAL*8中,它可以读取字符和实数,这将使您更容易获得帮助。我必须说,我很想知道这是怎么做到的。