-3

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

  1. 为什么我们在写入文件之前调用反向函数。

  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 %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;
}
4

2 回答 2

2

reverse()反转字节顺序,具体取决于平台。这里显示的似乎只是非 SPARC 版本的reverse() See endianness

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

于 2013-07-03T12:31:04.337 回答
1

这是一些非常糟糕的代码。你在这里复制也犯了一些错误:你复制GdsRecord了两次,i变量 inGdsBlock::write没有声明。

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

但是,它似乎没有short用大端写 s,这很奇怪,因为我很确定这意味着它无论如何都不会在 sparc/x86 互操作性中工作。我不确定什么字节序 sparc 用于doubles,因此该部分可能会或可能不会起作用。此外,如果类型不是,我无法得出GdsBlock::write仅部分写入数据的读数char

于 2013-07-03T12:34:14.670 回答