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

时间:2013-07-03 12:21:10

标签: c++ endianness

我正在研究非常遗留的代码,即迁移到32位到64位的机器。通常写入文件的数据在32位工作正常但在64位机器上有问题。当我检查文件并发现它通常包含32位值的4的除法。我的意思是,如果我们在32位机器中有80个值,那么在64位机器中它将是20个。(大多数情况下)。我查看了下面的代码,无法理解一些功能。

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

  2. 反向功能的目的是什么。

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

  4. 我试图采取一些代码来帮助我简要解释一下问题。请让我们 我知道是否需要提供更多信息。

    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 %X\n",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 %X\n",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 !this\n");
    
      if (!outstr)
        error.printf_exit ("GdsBlock::write  Error - outstr == 0\n");
    
      err = ferror(outstr);
      cout<< __LINE__<<"    "<<__PRETTY_FUNCTION__<<endl;
      if (err)
        { {
        char  *s = strerror (err);
        fclose (outstr);
        error.printf_exit ("GdsBlock::write  error - %s, errno %d\n", 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 :: external\n", (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 %d\n", s, err);
          }
    
        fclose (outstr);
        error.printf_exit("Error: bad header fwrite in GdsBlock :: write\n");
        }
    #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 %d\n", s, err);
          }
    
        fclose (outstr);
        error.printf_exit("Error: bad record fwrite in GdsBlock :: write\n");
        }
    #endif
    debug.printf("GdsBlock::write exit\n");
      TBX;
    }
    

2 个答案:

答案 0 :(得分:2)

reverse()会反转字节顺序,具体取决于平台。此处显示的似乎只是reverse()的非SPARC版本,请参见endianness

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

答案 1 :(得分:1)

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

无论如何,这似乎应该是这样做的(而且我完全不确定它是否正确,取决于GdsRecord::len的工作原理以及所有这些的确切含义 - 记录的字段和幻数是)以big-endian格式写int

然而,它似乎没有在big-endian中编写short,这很奇怪,因为我很确定这意味着它无论如何都不会在sparc / x86互操作性中起作用。我不确定sparc对double使用什么字节序,因此该部分可能会或可能不会起作用。此外,如果类型不是GdsBlock::write,我无法提供仅仅部分写入数据的char读数。