【问题标题】:Convert int to little-endian formated bytes in C++ for blobId in Azure在 C++ 中为 Azure 中的 blobId 将 int 转换为 little-endian 格式的字节
【发布时间】:2012-04-29 11:50:43
【问题描述】:

使用 Azure (http://msdn.microsoft.com/en-us/library/dd135726.aspx) 的 base64 编码,我似乎不知道如何取回所需的字符串。我可以在 C# 中执行以下操作。

int blockId = 5000;
var blockIdBytes = BitConverter.GetBytes(blockId);
Console.WriteLine(blockIdBytes);
string blockIdBase64 = Convert.ToBase64String(blockIdBytes);
Console.WriteLine(blockIdBase64);

打印出来(在 LINQPad 中):

Byte[] (4 items)
| 136         |
| 19          |
| 0           |
| 0           |

iBMAAA==

在 Qt/C++ 中,我尝试了一些 aporache,它们都返回了错误的值。

const int a = 5000;
QByteArray b;

for(int i = 0; i != sizeof(a); ++i) {
  b.append((char)(a&(0xFF << i) >>i));
}

qDebug() << b.toBase64(); // "iIiIiA==" 
qDebug() << QByteArray::number(a).toBase64(); // "NTAwMA=="
qDebug() << QString::number(a).toUtf8().toBase64(); // "NTAwMA=="

如何获得与 C# 版本相同的结果?

【问题讨论】:

  • 想想当i 为 1 时你的循环做了什么。当你想要 0xFF00 时,它将 0xFF 左移一位以获得 0x1FE。
  • 有没有更简单的方法可以在不使用 for 循环的情况下获得相同的结果?

标签: c# c++ qt qbytearray


【解决方案1】:

请参阅我对for 循环问题的评论。每次传递都会多移动一位,但实际上应该是 8 位。就个人而言,我更喜欢这个循环:

    b.append(static_cast<char>(a >> 24)); 
    b.append(static_cast<char>((a >> 16) & 0xff)); 
    b.append(static_cast<char>((a >> 8) & 0xff)); 
    b.append(static_cast<char>(a & 0xff)); 

以上代码用于网络标准字节顺序(大端)。将四个操作的顺序从最后到第一个翻转为小端字节序。

【讨论】:

  • 第一个append 不做&amp; 0xFF 有什么原因吗? (我会在所有这些上都这样做,尽管在具有 8 位字节的机器上,它不应该有所作为。)
  • @JamesKanze 第一次不需要,但它是无害的。我希望生成的代码完全相同。
  • 如果您使用的是 8 位字节的机器,它们中的任何一个都不需要它。由于a 具有带符号类型,因此如果机器具有其他大小的字节,则所有这些类型都需要。 (当然还有:[128...255] 范围内的值的转换是实现定义的,如果普通的char 是 8 位有符号的。在实践中,我从未见过它不起作用的实现。)跨度>
  • 是C++定义的溢出整数转换吗?我的回忆是结果是不确定的,但我经常犯这个错误。
  • 你的 byteArray 在调用 toBase64() 后给了我 "AAATiA==" 这是不正确的
【解决方案2】:

我最终做了以下事情:

QByteArray temp;
int blockId = 5000;

for(int i = 0; i != sizeof(blockId); i++) {
  temp.append((char)(blockId >> (i * 8)));
}

qDebug() << temp.toBase64(); // "iBMAAA==" which is correct

【讨论】:

  • 这给出了与大卫施瓦茨所做的不同的结果。哪一个是正确的?
  • 这个结果和 c# 的结果一样,至少 base 64 编码的字符串看起来是一样的
  • 这将转换为 little-endian 格式。我的代码以大端格式转换。 docs 表示原始代码使用 little-endian 格式。
  • 然后我需要的是 little-endian,因为我需要复制 c# 版本,而不仅仅是能够转换为字节数组。无论如何谢谢:)
【解决方案3】:

我认为这会更清楚,虽然可能会声称风格不良......

int i = 0x01020304;
char (&bytes)[4] = (char (&)[4])i;

你可以直接使用 bytes[0], bytes[1], ... 来访问每个字节,然后对它们做任何你想做的事情。

【讨论】:

  • 我的意思是你可以在之后做“b.append(bytes[0])”的事情。如果是 little-endian,则为 0 到 3,如果是 big-endian,则为 3 到 0。它比移位更不容易出错,您可以专注于字节顺序。
  • 它不是便携的;您必须根据字节顺序对其进行调整,它假设int 是32 位,并且在少数不使用2 的补码或在int 中有填充位的机器上完全失败。移位准确地说明了正在发生的事情:字节 n 中的 8 位是最终 int 中的 i...j 位。
  • 这个根本没用。产生了base64“BAMCAbDzMAEB”
  • 他显然在搞乱每个字节。现在看来他根本不明白自己在做什么……4字节的数据怎么能编码成66位……
  • 他可能推动了指针,将其解释为 C 风格、以 nul 结尾的字符串,但事实并非如此。
猜你喜欢
  • 1970-01-01
  • 2018-12-09
  • 1970-01-01
  • 2022-06-10
  • 1970-01-01
  • 2017-08-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多