c++ - 将 zlib 与 const 数据一起使用

c++ - Using zlib with const data

要使用 zlib 获取 compress/decompress 数据,首先我需要设置一个名为 z_stream 的结构。 z_stream 有两个非常量指针 next_innext_out.

如果我想做这样的功能:

void ungzip(std::vector<unsigned char>& dst,const std::vector<unsigned char>& src)
{
  z_stream strm;
  // more code
}

和其他类似的,

void gzip  (std::vector<unsigned char>& dst,const std::vector<unsigned char>& src);

我该怎么办?

复制src到本地std::vector<unsigned char>

std::vector<unsigned char> tmp(src);

并像这样将其用作源或设置指针,strm.next_in = const_cast<char*>(&src[0])

zlib 是否保留输入数据?

可能最简洁的方法是在编译时只定义 ZLIB_CONST,这样输入指针就被定义为 const unsigned char *

但是请注意,简单地丢弃 const-ness 确实可行(如果指向的字符实际上不是常量,这是合法的)。 代码应该是:

strm.next_in = (unsigned char *)&src[0];

或者更丑陋的 const_cast 变体,如果你喜欢那种东西。

请注意,zlib 中的默认设置未定义 ZLIB_CONST,如果您想使用预编译的 zlib 二进制文件,则转换解决方案是最佳选择。仅当您也使用相同的 define(1).

自己编译库时,才应该选择 ZLIB_CONST 解决方案

(1) 为编译器提供具有不同语义含义的 header 是一个坏主意 - 并且正式违反 C++ 标准规则 - 它可能 - 至少在理论上 - 会产生可移植性问题。

对于 X86 架构,情况可能并非如此,使用或不使用 ZLIB_CONST 编译的库将以完全相同的字节结束;但是也有不同的架构。

例如,我一直在使用 CPU,其中有不同的指针寄存器用于不同的对齐方式。在那个 CPU 中,从一个不是倍数或 4 的地址读取的整数是生成硬件陷阱的错误(此外,当时令我惊讶的是,即使只是分配指针 a [=54 也会触发错误=] 地址,即使该未对齐的地址从未用于读取或写入)。

我没有检查那个编译器(我只在 high-level 软件上工作)但是如果系统 ABI 指定函数 void foo(char *)void bar(int *) 必须在不同的寄存器中接收参数。

更重要的是,我从未使用过但我可以想象可能存在某些寄存器(我们将其命名为 RW0)可用于 reading/writing 操作和其他操作的 CPU 或 VM寄存器(例如 R0)只能用于读取。 使用这样的体系结构,ABI 可以指定类型 const char * 的第一个参数必须在 R0 中传递,而类型 char * 的第一个参数必须在 RW0 中传递。

如果是这种情况,用函数 void foo(char *p){...} 编译库,然后使用 as 声明编译调用代码 void foo(const char *p); 实际上最终会在错误的寄存器中传递地址!