C++ - 使用zlib处理常量数据

4

要使用zlib压缩/解压数据,首先需要设置一个名为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是否保留输入数据?


我建议通过迭代器接受输入:采用这种设计,可以限制调用者将数据存储在 vector<unsigned char> 中。 - M.M
1
zlib 不会修改输入数据。它被视为 const。默认情况下,next_in 不是 const,因为许多应用程序在 zlib 之外使用 next_in 读取其数据。将其设置为 const 将破坏这些应用程序。 - Mark Adler
1个回答

3

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

但请注意,简单地强制转换去掉常量属性确实可以工作(如果指向的字符实际上并不是常量,则合法)。 此代码应为:

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

或者更丑陋的const_cast变体,如果你喜欢的话。
需要注意的是,在zlib中默认情况下未定义ZLIB_CONST,如果想使用预编译的zlib二进制文件,则转换解决方案是最佳选择。只有在您自己编译具有相同定义(1)的库时才应该选择ZLIB_CONST解决方案。

(1) 给编译器提供具有不同语义含义的标头是一个坏主意——也是对C++标准规则的正式破坏——它可能会(至少在理论上)创建可移植性问题。

在X86架构中,这可能不是个问题,编译了或没有编译ZLIB_CONST的库将以完全相同的字节结束;然而还有其他不同的架构。

例如,我曾经使用过CPU,其中有不同的指针寄存器用于不同的对齐方式。在那些CPU中,从地址中读取整数,如果该地址不是4的倍数,则会生成硬件陷阱的错误(此外,当时让我惊讶的是,即使仅将指针分配给非对齐地址,也会触发错误,即使从未使用该非对齐地址进行读取或写入)。

对于这个编译器,我没有检查(我只在高级软件上工作),但如果系统ABI规定函数void foo(char *)void bar(int *)必须在不同的寄存器中接收参数,那么我也不会感到惊讶。

更重要的是,虽然我从未使用过,但我可以想象可能存在某些CPU或VM,其中某些寄存器(我们将一个称为RW0)可用于读写操作,而其他寄存器(例如R0)仅可用于读取。对于这样的架构,ABI可能会指定类型const char *的第一个参数必须传递给R0,而类型char *的第一个参数必须传递给RW0

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


如果我正在使用Linux发行版提供的软件包,那么我是否需要为我的程序重新编译zlib? - R. F. Luis
@R.F.Luis:那就选择第二个选项吧:只需传递 (char *)&src[0]std::vector 中的数据不能是 const,强制转换掉 const 是安全的。 - 6502
src 是一个 const std::vector<unsigned char>&,因此数据必须是 const 的,并且需要使用 const_cast 进行转换。如果对象被 const 限定符 限定,则无法更改它。 - R. F. Luis
@R.F.Luis:const属性的概念比这个稍微复杂一些,而且const数据和const引用之间存在差异。更具体地说,仅使用引用的术语const表达了引用的属性,并且对被引用的数据没有任何说明:包含在std::vector中的字符不能是const...因此,从绑定到向量的const引用中去除const属性总是安全的。 - 6502
我不明白你指的是什么。以下代码 #include <vector>void sum(const std::vector<int>& data){ if (data.size()>2) for (int i=1;i<data.size();i++) data[0]+=data[i]; return; } 在使用g++编译时会出现以下错误:const-vector.cpp: In function ‘void sum(const std::vector<int>&)’: const-vector.cpp:4:69: error: assignment of read-only location ‘(& data)->std::vector<int>::operator[](0)’ if (data.size()>2) for (int i=1;i<data.size();i++) data[0]+=data[i]; - R. F. Luis
显示剩余10条评论

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