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

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-10 18:37:57

问题


I am migrating some legacy Fortran77 code to C/C++. In the Fortran77 code, if 8 characters are read in from a file, they can be stored in a variable of type real*8 without a problem.

Is it possible to do a similar thing in C or C++? If so, how would I do it? I haven't been able to find any solutions on the internet. I need to read in 8 characters using C/C++ and store them in a variable of type double, which is then passed back to Fortran and corresponds to the original real*8 variable.

Many thanks in advance for any help.

EDIT: In response to @sixlettervariables, I'll just clarify my use-case a bit more. The issue I have with his suggestion is that I only know the format of each line (i.e. which fields are strings, which numbers) at runtime, and hence I can't know what members the struct should have statically. The fields also need to occupy a contiguous block of memory in the order they are read in.

Concretely, in one run of the program the format of each line might be: f1:string, f2:number, f3:number, f4:string, but in another f1:string, f2:string, f3:string, f4:number, f5:number. For the first case I'd need:

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

For the second I'd need:

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

Perhaps there is some way to do this with templates?


回答1:


You do not need to store them in a double just because Fortran needed to do that. In fact, you absolutely should not do that in your C/C++ code.

Simply store the character data in a character array.

If you're mixing Fortran and C/C++, the two have no idea about one another outside of their ABI. From the C side you can simply claim that the Fortran interface takes a character array, when in fact it is expecting an array of doubles. And the same is true from the Fortran side.

From the C side:

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 \0 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] == '\0') {
        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 '\0') instead.
 */
FCHARS(str, flength);

As long as you follow the ABI requirements of your Fortran compiler (e.g. CDECL, hidden string lengths passed interleaved) from the C/C++ code, you'll be fine.




回答2:


Sure, just use a cast. You might want to add a static_assert for safety:

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



回答3:


union Data{
    char c[8];
    double d;
};

Save the 8 characters into c, and read it by d. Example:

#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("%e\n", data.d);
    // system("pause");
    return 0;
}



回答4:


method 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.
}

method 2

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



回答5:


Even if it would be possible in C to store several chars and real numbers in a DOUBLE variable because C DOUBLE is equal to REAL*8 because both are double precision float numbers I would strongly advise against it.

This "trick" to store several chars and reals in REAL*8 feels like a hack to save space. I don't think this is needed nowadays and I do not think this "trick" would generate faster code. I would advise to use a UNION as mentioned above.

You could post the FORTAN code which reads the chars and reals into the REAL*8 this would make it easier to help you. And I must say I am intrigued to find out how this is done.



来源:https://stackoverflow.com/questions/16463080/is-it-possible-to-store-8-characters-1-byte-each-in-a-variable-of-type-double

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!