将c++代码从32位机器迁移到64位机器

migration c++ code 32 bit machine to 64 bit machine

本文关键字:机器 迁移 64位 32位 c++ 代码      更新时间:2023-10-16

我正在处理非常传统的代码,即从32位迁移到64位机器。我通常会用在32位运行良好但在64位机器中有问题的数据写入文件。当我检查文件时,发现它通常包含32位值的4除法。我的意思是,如果我们在32位机器中有80个值,那么在64位机器中就会有20个值。(大多数情况下)。我已经研究了下面的一段代码,但无法理解其中的一些功能。

  1. 为什么我们在写入File之前调用reverse函数。

  2. 反向函数的目的是什么。

  3. 在write函数中,尽管我们有任何数据类型,但我们总是写one_ascii值。

我试着用一些代码来帮助我简单地解释这个问题。请让我知道是否需要提供更多信息。

class  GdsHeader
{
public:
  unsigned  short  rlen;
  char      record_type;
  char      data_type;
};
class  GdsRecord
{
public:
#ifndef SWIG
  union
    {
    short    *two_int;
    int     *four_int;
    double   *eight_real;
    char     *one_ascii;
//    void    *v;
    };
#endif
  int  length;
      GdsRecord (); // { v = 0; length = 0; }
      ~GdsRecord ()  ;//  { delete v; }
  void  len (int l, int type);
};


    class  GdsBlock
    {
      bool      valid_block ();
      int      len;
    public:
      bool      record_unred;
      int      header_ftell;
      GdsHeader  h;
      GdsRecord  r;
      int      array_size;
    //  bool      re_read;
    //          GdsBlock () { re_read = false; }
              GdsBlock () { record_unred = false; header_ftell = 0; }
      void      set (int rt, int dt, int sz)
                {TBE;
                h.record_type = rt;    h.data_type = dt;
                array_size = sz;       r.len (sz, dt);TBX;
                }
       int      read_header (FILE *);
      void      read_block (FILE *);
      void      write (FILE *);
      void      prt ();
    };

    void  GdsRecord :: len (int l, int type)
{
  switch (type)
    {
    case STREAM_Bit_array:
    case STREAM_Short:  l *= 2; break;
    case STREAM_Long:    l *= 4; break;
    case STREAM_Double:  l *= 8; break;
    }
  if (l > length)
    {
    l = ((l / 8) + 2) * 8;
    if (one_ascii) delete [] one_ascii;
    one_ascii = new char[l];
    debug2.printf("GdsRecord::len  new one_ascii  len %d   one_ascii %Xn",l, one_ascii);
    length = l;
    }
}

#ifndef sparc
        static  void  reverse (int len, char *buf)
        {
          TBE;
          char  tmp[24];
         int  i;
          for (i = 0; i < len; i++) tmp[i] = buf[i];
          for (i = 0; i < len; i++) buf[i] = tmp[ (len - 1) - i];
          TBX;
        }
        inline  void  reverse (int len, short *s)  { reverse (len, (char *) s); }
        inline  void  reverse (int len, int *s)    {  reverse (len, (char *) s); }
        inline  void  reverse (int len, double *s)  { reverse (len, (char *) s); }
        inline  void  reverse (int len, unsigned char *s)  {reverse (len, (char *) s); }
        #endif
void    GdsBlock :: write (FILE *outstr)
{
TBE;
debug.printf("GdsBlock::write %Xn",outstr);
  int  i, err;
  char  *c, tmp;
  if (h.data_type == 3)
  {
      cout<<"Begin...blk.r.four_int[0] =>"<<r.four_int[0]<<endl;
  }
  if (!this)
    error.printf_exit("GdsBlock::write error !thisn");
  if (!outstr)
    error.printf_exit ("GdsBlock::write  Error - outstr == 0n");
  err = ferror(outstr);
  cout<< __LINE__<<"    "<<__PRETTY_FUNCTION__<<endl;
  if (err)
    { {
    char  *s = strerror (err);
    fclose (outstr);
    error.printf_exit ("GdsBlock::write  error - %s, errno %dn", s, err);
    }
  switch(h.data_type)
    {
    case 0: /* NO DATA */
      h.rlen = 4;
  cout<< __LINE__<<"    "<<__PRETTY_FUNCTION__<<endl;
      break;
      case 1: /* BIT ARRAY */
  cout<< __LINE__<<"    "<<__PRETTY_FUNCTION__<<endl;
#ifndef sparc
       reverse (2, &r.two_int[0]);
#endif
      h.rlen = (2 * array_size) + 4;
      break;
      case 2: /* TWO BYTE SIGNED INTEGER */
  cout<< __LINE__<<"    "<<__PRETTY_FUNCTION__<<endl;
#ifndef sparc
      for (i = 0; i < array_size; i++)    reverse(2,&r.two_int[i]);
#endif
      h.rlen = (2 * array_size) + 4;
      break;
      case 3: /* FOUR BYTE SIGNED INTEGER */
  cout<< __LINE__<<"    "<<__PRETTY_FUNCTION__<<endl;
#ifndef sparc
      for(i = 0; i < array_size; i++)
      {
          cout<<r.four_int[i]<<endl;
          int *temp = &r.four_int[i];
          reverse(4,temp);
          //print_stacktrace();
          cout<<r.four_int[i]<<endl;
          //r.four_int[i] = r.four_int[i] << 2 ;
      }
#endif
      h.rlen = (4 * array_size) + 4;
      break;
      case 5: /* EIGHT BYTE REAL */
  cout<< __LINE__<<"    "<<__PRETTY_FUNCTION__<<endl;
#ifndef  FPC
        for (i = 0; i < array_size; i++)    getr ((CONV *) (r.eight_real + i));
#endif
#ifdef  FPC
        for (i = 0; i < array_size; i++)    fpc (r.eight_real + i);
#endif
      h.rlen = (8 * array_size) + 4;
      break;
      case 6: /* CHARACTER ARRAY */
  cout<< __LINE__<<"    "<<__PRETTY_FUNCTION__<<endl;
      h.rlen = array_size + 4;
      break;
    default:
      error.printf_exit("Error: bad record type %d in GdsBlock :: externaln", (int) h.data_type);
      }
  if (h.rlen % 2)
    {
    r.one_ascii[h.rlen] = 0;
    h.rlen++;
    }
  cout<< __LINE__<<"    "<<__PRETTY_FUNCTION__<<endl;
  i = h.rlen - 4;
#ifndef sparc
  c = (char *) &h.rlen;
  tmp = c[0];
  c[0] = c[1];
  c[1] = tmp;
#endif
  err = fwrite (&h, 1, sizeof (h), outstr);
  if (err != sizeof(h))
    {
    err = ferror(outstr);
    if (err)
      {
      char  *s = strerror (err);
      fclose (outstr);
      error.printf_exit ("GdsBlock::write  error - %s, errno %dn", s, err);
      }
    fclose (outstr);
    error.printf_exit("Error: bad header fwrite in GdsBlock :: writen");
    }
#if 1
  err = fwrite (r.one_ascii, 1, i, outstr);
  if (err != i)
    {
    err = ferror(outstr);
    if (err)
   {
      char  *s = strerror (err);
      fclose (outstr);
      error.printf_exit ("GdsBlock::write  error - %s, errno %dn", s, err);
      }
    fclose (outstr);
    error.printf_exit("Error: bad record fwrite in GdsBlock :: writen");
    }
#endif
debug.printf("GdsBlock::write exitn");
  TBX;
}

reverse()根据平台反转字节顺序。这里显示的似乎只是reverse()的非SPARC版本请参阅endianness。

在写入文件之前反转字节顺序(即调用reverse())的原因是为了使文件格式平台(即endianness)独立。

这是一些非常糟糕的代码。您在这里复制它时也犯了一些错误:您复制了GdsRecord两次,并且GdsBlock::write中的i变量没有声明。

无论如何,这似乎应该做的是(我完全不确定它是否做了正确的事情,这取决于GdsRecord::len是如何工作的,以及所有这些未充分记录的字段和幻数的确切含义是什么)以big-endian格式编写int

然而,它似乎没有用big-endian编写shorts,这很奇怪,因为我很确定这意味着它无论如何都不能在sparc/x86互操作性中工作。我不确定在doubles中使用什么endianness sparc,所以该部分可能工作,也可能不工作。此外,如果类型不是char,我无法想出不部分写入数据的GdsBlock::write读取方法。