快速字节复制 C++11

发布于 2025-01-16 06:41:25 字数 1433 浏览 2 评论 0原文

我需要转换广泛使用字节操作的 C# 应用程序。

一个例子:

    public abstract class BinRecord
    {
        public static int version => 1;

        public virtual int LENGTH => 1 + 7 + 8 + 2 + 1; // 19

        public char type;
        public ulong timestamp; // 7 byte
        public double p;
        public ushort size;
        public char callbackType;

        public virtual void FillBytes(byte[] bytes)
        {
            bytes[0] = (byte)type;

            var t = BitConverter.GetBytes(timestamp);
            Buffer.BlockCopy(t, 0, bytes, 1, 7);

            Buffer.BlockCopy(BitConverter.GetBytes(p), 0, bytes, 8, 8);
            Buffer.BlockCopy(BitConverter.GetBytes(size), 0, bytes, 16, 2);
            bytes[18] = (byte)callbackType;
        }
    }

基本上,BitConverterBuffer.BlockCopy 每秒调用 100 次。

有几个类继承了上面的基类,执行更具体的任务。例如:

    public class SpecRecord : BinRecord
    {
        public override int LENGTH => base.LENGTH + 2;
        public ushort num;

        public SpecRecord() { }
        public SpecRecord(ushort num)
        {
            this.num = num;
        }

        public override void FillBytes(byte[] bytes)
        {
            var idx = base.LENGTH;
            base.FillBytes(bytes);

            Buffer.BlockCopy(BitConverter.GetBytes(num), 0, bytes, idx + 0, 2);
        }
    }

我应该研究 C++ 中的哪种方法?

I need to convert C# app which uses extensively bytes manipulation.

An example:

    public abstract class BinRecord
    {
        public static int version => 1;

        public virtual int LENGTH => 1 + 7 + 8 + 2 + 1; // 19

        public char type;
        public ulong timestamp; // 7 byte
        public double p;
        public ushort size;
        public char callbackType;

        public virtual void FillBytes(byte[] bytes)
        {
            bytes[0] = (byte)type;

            var t = BitConverter.GetBytes(timestamp);
            Buffer.BlockCopy(t, 0, bytes, 1, 7);

            Buffer.BlockCopy(BitConverter.GetBytes(p), 0, bytes, 8, 8);
            Buffer.BlockCopy(BitConverter.GetBytes(size), 0, bytes, 16, 2);
            bytes[18] = (byte)callbackType;
        }
    }

Basically BitConverter and Buffer.BlockCopy called 100s times per sec.

There are several classes that inherit from the base class above doing more specific tasks. For example:

    public class SpecRecord : BinRecord
    {
        public override int LENGTH => base.LENGTH + 2;
        public ushort num;

        public SpecRecord() { }
        public SpecRecord(ushort num)
        {
            this.num = num;
        }

        public override void FillBytes(byte[] bytes)
        {
            var idx = base.LENGTH;
            base.FillBytes(bytes);

            Buffer.BlockCopy(BitConverter.GetBytes(num), 0, bytes, idx + 0, 2);
        }
    }

What approach in C++ should I look into?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

娇俏 2025-01-23 06:41:26

在我看来,最好的选择是实际使用 C - 使用 memcpy 复制任何对象的字节。

然后,您的上述代码将被重写如下:

void FillBytes(uint8_t* bytes)
{
     bytes[0] = (uint8_t)type;
     memcpy((bytes + 1), &t, sizeof(uint64_t) - 1);
     memcpy((bytes + 8), &p, sizeof(double));
     memcpy((bytes + 16), &size, sizeof(uint16_t));
     bytes[18] = (uint8_t)callbackType;
}

这里,我使用 uint8_tuint16_tuint64_t 作为 的替换byteushortulong 类型。

请记住,您的时间戳副本无法移植到大端 CPU - 它会截断最低字节而不是最高字节。解决这个问题需要手动复制每个字节,如下所示:

//Copy a 7 byte timestamp into the buffer.
bytes[1] = (t >> 0) & 0xFF;
bytes[2] = (t >> 8) & 0xFF;
bytes[3] = (t >> 16) & 0xFF;
bytes[4] = (t >> 24) & 0xFF;
bytes[5] = (t >> 32) & 0xFF;
bytes[6] = (t >> 40) & 0xFF;
bytes[7] = (t >> 48) & 0xFF;

Best option, in my opinion, is to actually go to C - use memcpy to copy over the bytes of any object.

Your above code would then be re-written as follows:

void FillBytes(uint8_t* bytes)
{
     bytes[0] = (uint8_t)type;
     memcpy((bytes + 1), &t, sizeof(uint64_t) - 1);
     memcpy((bytes + 8), &p, sizeof(double));
     memcpy((bytes + 16), &size, sizeof(uint16_t));
     bytes[18] = (uint8_t)callbackType;
}

Here, I use uint8_t, uint16_t, and uint64_t as replacements for the byte, ushort, and ulong types.

Keep in mind, your timestamp copy is not portable to a big-endian CPU - it will cut off the lowest byte rather than the highest. Solving that would require copying in each byte manually, like so:

//Copy a 7 byte timestamp into the buffer.
bytes[1] = (t >> 0) & 0xFF;
bytes[2] = (t >> 8) & 0xFF;
bytes[3] = (t >> 16) & 0xFF;
bytes[4] = (t >> 24) & 0xFF;
bytes[5] = (t >> 32) & 0xFF;
bytes[6] = (t >> 40) & 0xFF;
bytes[7] = (t >> 48) & 0xFF;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文