代码之家  ›  专栏  ›  技术社区  ›  Cinder Biscuits

从字节数组中解包整数

  •  0
  • Cinder Biscuits  · 技术社区  · 6 年前

    如果这是完全明显的,请原谅我,但我正在使用字节数组通过网络发送数据,我需要在其中填充一个整数,然后在另一端将其取出。

    示例中的类型定义:

    uint8_t *dest;
    uint8_t *ciphertext;
    size_t  cbytes; // length of ciphertext
    uint8_t iv[16];
    uint8_t tag[16];
    

    作者的相关部分:

    size_t bytes = 0;
    memcpy(&dest[bytes], iv, sizeof(iv));
    bytes = sizeof(iv);
    memcpy(&dest[bytes], (void*)htonl(cbytes), sizeof(uint32_t));
    bytes += sizeof(uint32_t);
    memcpy(&dest[bytes], ciphertext, cbytes);
    bytes += cbytes;
    memcpy(&dest[bytes], tag, sizeof(tag));
    bytes += sizeof(tag);
    

    这是填东西的正确方法吗 cbytes ,作为一个整数进入字节数组?如果不是,有什么更好的方法?

    现在,使用这个字节数组,我应该如何读取 字节 返回整数(或大小T)?它的其余部分可以复制出来,但不确定如何处理整数。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Antti Haapala -- Слава Україні    6 年前

    你在问这段代码:

    memcpy(&dest[bytes], (void*)htonl(cbytes), sizeof(uint32_t));
    

    不,完全不正确。您正在转换的返回值 htonl 指向一个指针。但它不是有效的指针。你 具有类型的对象 uint32_t 发送:

    uint32_t cbytes32 = htonl(cbytes);
    memcpy(&dest[bytes], &cbytes32, sizeof(uint32_t));
    

    在现代的C语言中,使用 复合文字 创建一个数组 UIT32 内联:

    memcpy(&dest[bytes], (uint32_t[]){ htonl(cbytes) }, sizeof(uint32_t));
    

    但是语法看起来确实不太好。

    要读取它,需要将其读取到类型为的对象 UIT32 然后 ntohl 它和您可以存储到的返回值 size_t :

    uint32_t size32;
    size_t size;
    memcpy(&size32, src, sizeof size32)
    size = ntohl(size32);
    

    那么,我会格外小心你可能用了64位 西泽特 其他地方,但在这里将其截断为32位。也许可以,但这需要记录下来。64位应该足够所有人使用,但不幸的是没有 htonll 功能。


    最后,而不是 &dest[bytes] 你可以写 dest + bytes 减少按键次数。甚至更少,你可以做另一个指针:

    uint8_t *cur = dest;
    memcpy(cur, iv, sizeof iv);
    cur += sizeof iv;
    uint32_t cbytes32 = htonl(cbytes);
    memcpy(cur, &cbytes32, sizeof cbytes32);
    cur += sizeof cbytes32;
    memcpy(cur, ciphertext, cbytes32);
    cur += cbytes32;
    memcpy(cur, tag, sizeof tag);
    cur += sizeof tag;
    size_t nbytes = cur - dest;
    

    注意,如果使用 流式套接字 (TCP)通常不需要将它们复制到中间缓冲区-只需使用单独的 read 打电话——或者至少,不要费心复制 长的 在大小调用后数组到同一个缓冲区中。