【问题标题】:c; converting 2 bytes to short and vice versaC;将 2 个字节转换为短字节,反之亦然
【发布时间】:2014-08-22 01:17:46
【问题描述】:

我想将字节数组bytes1 (little endian) 2 x 2 转换为短整数数组,反之亦然。我希望得到最终数组bytes2,等于初始数组bytes1。我有这样的代码:

  int i = 0;
  int j = 0;

  char *bytes1;
  char *bytes2;
  short *short_ints;

  bytes1 = (char *) malloc( 2048 );
  bytes2 = (char *) malloc( 2048 );
  short_ints = (short *) malloc( 2048 );

  for ( i=0; i<2048; i+=2)
   {
     short_ints[j] = bytes1[i+1] << 8 | bytes1[i] ;
     j++;
   }

  j = 0;

  for ( i=0; i<2048; i+=2)
     {
        bytes2[i+1] = (short_ints[j] >> 8)  & 0xff;
        bytes2[i] = (short_ints[j]) ;
        j++;
     }
  j = 0;

现在,谁能告诉我为什么我没有bytes2 数组,和bytes1 完全一样?以及如何正确地做到这一点?

【问题讨论】:

  • 它们有何不同以及在哪里不同?对于较小的输入,预期和实际输出是多少?
  • 输入不小;它是 2048 字节。许多元素不同,它们的索引都在 1000 以上。在索引 1000 以下,所有元素都是相等的。
  • 您似乎左移到符号位并将其移回。这是实现定义的,并且可能符号位也被移位。根据经验,按位运算始终使用无符号类型。
  • 因为你在使用之前没有初始化bytes1数组,所以你不知道你会得到什么。
  • 不,你不想用有符号字节来做;你会在某个时候投射到unsigned

标签: c type-conversion


【解决方案1】:

建议 2 个函数。将所有组合和提取作为无符号进行,以消除shortchar 中符号位的问题。

符号位是 OP 的代码最大的问题。 short_ints[j] = bytes1[i+1] &lt;&lt; 8 | bytes1[i] ; 可能会通过 bytes1[i] 转换为 int 扩展符号。
(short_ints[j] &gt;&gt; 8) 也扩展了符号。

// Combine every 2 char (little endian) into 1 short
void charpair_short(short *dest, const char *src, size_t n) {
  const unsigned char *usrc = (const unsigned char *) src;
  unsigned short *udest = (unsigned short *) dest;
  if (n % 2) Handle_OddError();
  n /= 2;
  while (n-- > 0) {
    *udest = *usrc++;
    *udest += *usrc++ * 256u;
    udest++;
  }
}

// Break every short into 2  char (little endian)
void short_charpair(char *dest, const short *src, size_t n) {
  const unsigned short *usrc = (const unsigned short *) src;
  unsigned char *udest = (unsigned char *) dest;
  if (n % 2) Handle_OddError();
  n /= 2;
  while (n-- > 0) {
    *udest++ = (unsigned char) (*usrc);
    *udest++ = (unsigned char) (*usrc / 256u);
    usrc++;
  }
}

int main(void) {
  size_t n = 2048;  // size_t rather than int has advantages for array index

  // Suggest code style: type *var = malloc(sizeof(*var) * N);
  // No casting of return
  // Use sizeof() with target pointer name rather than target type.
  char *bytes1 = malloc(sizeof * bytes1 * n);
  Initialize(bytes, n); //TBD code for OP-best to not work w/uninitialized data

  // short_ints = (short *) malloc( 2048 );
  // This is weak as `sizeof(short)!=2` is possible

  short *short_ints = malloc(sizeof * short_ints * n/2);
  charpair_short(short_ints, bytes1, n);

  char *bytes2 = malloc(sizeof * bytes2 * n);
  short_charpair(bytes2, short_ints, n);

  compare(bytes1, bytes2, n); // TBD code for OP

  // epilogue 
  free(bytes1);
  free(short_ints);
  free(bytes2);
  return 0;
}

避免使用union 方法,因为它依赖于平台字节序。

【讨论】:

    【解决方案2】:

    这是一个程序,表明您遇到了与位移有符号整数值相关的问题。

    #include <stdio.h>
    #include <stdlib.h>
    
    void testCore(char bytes1[],
                  char bytes2[],
                  short short_ints[],
                  int size)
    {
       int i = 0;
       int j = 0;
    
       for ( i=0; i<size; i+=2)
       {
          short_ints[j] = bytes1[i+1] << 8 | bytes1[i] ;
          j++;
       }
    
       j = 0;
    
       for ( i=0; i<size; i+=2)
       {
          bytes2[i+1] = (short_ints[j] >> 8)  & 0xff;
          bytes2[i] = (short_ints[j]) ;
          j++;
       }
    
       for ( i=0; i<size; ++i)
       {
          if ( bytes1[i] != bytes2[i] )
          {
             printf("%d-th element is not equal\n", i);
          }
       }
    }
    
    void test1()
    {
       char bytes1[4] = {-10, 0, 0, 0};
       char bytes2[4];
       short short_ints[2];
       testCore(bytes1, bytes2, short_ints, 4);
    }
    
    void test2()
    {
       char bytes1[4] = {10, 0, 0, 0};
       char bytes2[4];
       short short_ints[2];
       testCore(bytes1, bytes2, short_ints, 4);
    }
    
    int main()
    {
       printf("Calling test1 ...\n");
       test1();
       printf("Done\n");
       printf("Calling test2 ...\n");
       test2();
       printf("Done\n");
       return 0;
    }
    

    程序的输出:

    调用 test1 ... 第一个元素不相等 完毕 调用 test2 ... 完毕

    Udate

    这是一个适合我的testCore 版本:

    void testCore(char bytes1[],
                  char bytes2[],
                  short short_ints[],
                  int size)
    {
       int i = 0;
       int j = 0;
       unsigned char c1;
       unsigned char c2;
       unsigned short s;
    
       for ( i=0; i<size; i+=2)
       {
          c1 = bytes1[i];
          c2 = bytes1[i+1];
          short_ints[j] = (c2 << 8) | c1;
          j++;
       }
    
       j = 0;
    
       for ( i=0; i<size; i+=2)
       {
          s = short_ints[j];
          s = s >> 8;
          bytes2[i+1] = s;
          bytes2[i] = short_ints[j] & 0xff;
          j++;
       }
    
       for ( i=0; i<size; ++i)
       {
          if ( bytes1[i] != bytes2[i] )
          {
             printf("%d-th element is not equal\n", i);
          }
       }
    }
    

    通过以下方式测试:

    char bytes1[4] = {-10, 0, 25, -4};
    

    char bytes1[4] = {10, -2, 25, 4};
    

    【讨论】:

    • 是的,您找到了原因。但是你为什么不修改代码让它工作呢?无论这些其他解决方案如何
    【解决方案3】:

    嗯,你需要的是一个 UNION:

    #include <stdio.h>
    #include <string.h>
    
    union MyShort {
        short short_value;
        struct {
            char byte1;
            char byte2;
        };
    };
    
    int main(int argc, const char * argv[])
    {
        char a[4]="abcd";
        char b[4]="1234";
        short c[5]; c[4]=0;
        union MyShort d;
        for (int i = 0; i<4; i++) {
            d.byte1 = a[i];
            d.byte2 = b[i];
            c[i] = d.short_value;
        }//next i
        printf("%s\n", (char*)c);
        return 0;
    }
    

    结果应该是 a1b2c3d4。

    【讨论】:

    • 在我看来,OP 想要的是 little-endian,而不是平台的 endianness。
    猜你喜欢
    • 2015-02-16
    • 2014-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多