如何将无符号字符数组转换为无符号长长整型?

5

假设我有8个无符号字符,我想将它们转换为一个无符号长整型。

例如,如果所有的字符都等于0xFF,则无符号长整型将等于0xFFFFFFFFFFFFFFFF。

使用C或C++,最有效的方法是什么?


如果所有字符都不等于0xFF,会怎么样? - Kerrek SB
你是指0xFFFFFFFFFFFFFFFF吗? - user253751
2
你尝试过使用 *reinterpret_cast< unsigned long long * >( your_array ); 吗? - George Houpis
1
哪种语言,C还是C++?C语言没有reinterpret_cast - Thomas Matthews
1
大端或小端 - Rocky Pulley
显示剩余6条评论
3个回答

6

例如:

unsigned char buffer[8] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
unsigned long long target;
memcpy(&target, buffer, sizeof target);

请注意,如果buffer的所有元素值不相同,则结果将取决于字节顺序(小端 vs. 大端)。
此外,这还假定unsigned long long确切地为8个字节。虽然这很常见,但并不保证。(一个字节恰好为8位也不是保证,它可能更多。根据定义,unsigned char为1个字节。)

使用<stdint.h><cstdint>uint64_t将始终提供8个字节。 - Jason
3
@Jason:不,它总是会给出64位或64 / CHAR_BIT字节。但是如果你假设CHAR_BIT==8,那么是的,uint64_t总是8个字节(如果存在的话!)。 - Keith Thompson
非常正确, char 并不一定被定义为一个字节,这意味着 uint64_t 可能无法容纳整个字符串。使用 unsigned long long 时大小不匹配可能会更糟。 - Jason
@Jason:不,char 在 C 和 C++ 中的定义是一个字节。一个字节不一定是八位的八进制数;它可以更大。unsigned long long 至少有 64 位,但可以更大。另一方面,具有 CHAR_BIT > 8 的系统很少见(主要是 DSP),我从未见过大小不是恰好 64 位的 unsigned long long - Keith Thompson
@Jason:这就是C和C++标准定义byte的方式。 - Keith Thompson
显示剩余2条评论

5

你可以直接使用赋值操作代替memcpy复制位

  unsigned char buffer[8] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
  unsigned long long l = 0;
  for (int i = 0; i < 8; ++i) {
    l = l | ((unsigned long long)buffer[i] << (8 * i));
  }

我认为这是与字节序无关的。


0

非常抱歉我之前的回答有些愚蠢,应该更仔细地阅读问题。希望这个回答更有帮助。转换的方式取决于字节数组中 long long 表示的字节序是否与您所使用的架构相匹配。

C++:

#include <iostream>
#include <cstring>

using namespace std;

// Assuming ca is at least 8 bytes, the size of long long, interpret the
//    first 8 bytes as long long.
// differentEndian == true means the endianness of the machine is
//    different from the representation in ca.
long long getLongLong( unsigned char * ca, bool differentEndian )
{
   long long retVal;

   if (differentEndian)
   {
       for (int i = 0; i < 4; i++)
       {
           unsigned char _tmpCh = ca[i];
           ca[i] = ca[7-i];
           ca[7-i] = _tmpCh;
       }
   }
   retVal = *reinterpret_cast<unsigned long long *>(ca);

   return retVal;
}

int main()
{
   unsigned char cArray[] = {0xff, 0x1, 0x70, 0x2, 0x61, 0x3, 0x52, 0x4};

   unsigned long long ll = getLongLong( cArray, false );
   cout << "Result for same endian: " << hex << ll << " or " << dec << ll << endl;

   ll = getLongLong( cArray, true );
   cout << "Result for different endian: " << hex << ll << " or " << dec << ll << endl;

   return 0;
}

C:

#include <stdio.h>
#include <string.h>

// Assuming ca is at least 8 bytes, the size of long long, interpret the
//    first 8 bytes as long long.
// differentEndian != 0 means the endianness of the machine is
//    different from the representation in ca.
long long getLongLong( unsigned char * ca, int differentEndian )
{
   long long retVal;

   if (differentEndian)
   {
       int i;
       for (i = 0; i < 4; i++)
       {
           unsigned char _tmpCh = ca[i];
           ca[i] = ca[7-i];
           ca[7-i] = _tmpCh;
       }
   }
   memcpy( &retVal, ca, sizeof(long long));

   return retVal;
}

int main()
{
   unsigned char cArray[] = {0xff, 0x1, 0x70, 0x2, 0x61, 0x3, 0x52, 0x4};

   unsigned long long ll = getLongLong( cArray, 0 );
   printf("Result for same endian: %llx or %llu\n", ll, ll);

   ll = getLongLong( cArray, 1 );
   printf("Result for different endian: %llx or %llu\n", ll, ll);

   return 0;
}

两个版本的输出结果均为:

Result for same endian: 4520361027001ff or 311315039429591551
Result for different endian: ff01700261035204 or 1837509111016818739

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接