将 const std::vector<char> 转换为 unsigned char*?

Cast const std::vector<char> to unsigned char*?

为 C 库编写 C++ 包装器。在库中有一个函数接受缓冲区作为 unsigned char *。由于使用 C++,我将我的真实缓冲区存储在 std::vector<char> 中,此外,在包装器 class 中,我还添加了 const,因为有问题的缓冲区是一个输入缓冲区,它不会被修改。但是我的代码没有编译,demo:

#include <stdio.h>
#include <vector>

void x(unsigned char *s)
{
    printf("%s\n", s);
}

int main()
{
    const std::vector<char> s(10);

    x(reinterpret_cast<unsigned char *>(s.data())); // FAILS
}

id有什么问题?如果我从 const std::vector<char> s(10); 中删除 consts 它会起作用,但我更喜欢那样。

您的错误是因为您将 std::vector 声明为 const

如果你去掉常量,它就可以正常工作。 (如所见here

无论如何,您应该问问自己是否真的需要在数组中存储 charunsigned char

如果您想保留 const,则必须使用 const_cast,但您的行会变得很长:

x(const_cast<unsigned char*>(reinterpret_cast<const unsigned char *>(s.data())));

如果您有权访问该库,最好将缓冲区标记为 const(如果它未更改)。 但是,由于它不是 const,您不能确定它不会被函数修饰,因此,您不应该将 std::vector 保留为 const.

您必须执行 const_cast 删除常量,然后 reinterpret_castchar * 转换为 unsigned char *

试试这个:x(reinterpret_cast<unsigned char*>(const_cast<char *>(s.data())));

注意:但也请记住 const_cast 只有在转换最初是非常量的变量时才是安全的。请参阅 this 答案。

这就是我在跨平台实施过程中解决同样问题的方法。上述方法在 Windows 和 Linux (Redhat) 上运行良好,但在 Solaris 10 和 IBM AIX 7 上运行不佳。

Solaris 10 使用上述建议的方法给出以下错误。 'nofieldident: data is not a member of const std::vector<unsigned char>'

这是一种处理矢量数据 'const'ness 的方法,它适用于 Windows、Linux、Solaris

#include <iostream>
#include <vector>

using namespace std;

/// Data Interface, which is visible to the outside
class IDataInterface {
public:
        // Get the underlying data as a const data pointer
        virtual const unsigned char* Data(size_t& nSize) = 0;
};

/// Implemetation of the IDataInterface
class CData : public IDataInterface {
public:
        // Constructor
        CData(vector<unsigned char> data);

        // Overriden function of the interface
        const unsigned char* Data(size_t& nSize);

private:
        /// Actual data member
        vector<unsigned char> m_vData;
};

/// Constructor implementation
CData::CData(vector<unsigned char> vData) {
        // resize to the input data size
        m_vData.resize(vData.size());

        // Copy the data
        memcpy(&m_vData[0], &vData[0], vData.size());
}

/// Implementation of the data function
const unsigned char* CData::Data(size_t& nSize /**< Size of data returned */) {
        /*
         * Following four methods worked fine on Windows, RedHat, but Failed on Solaris 10 and IBM AIX
         */
        // return &m_vData[0];
        // return m_vData.data();
        // return const_cast<unsigned char*>(reinterpret_cast<const unsigned char *>(m_vData.data()));
        // return reinterpret_cast<unsigned char*>(const_cast<unsigned char *>(m_vData.data()));
        
        /* This was tested on following and works fine.
         * Windows (Tested on 2008 to 2016, 32/64 bit, R2 versions)
         * RedHat 5&7 (32/64 bit)
         * Solaris 10 (32/64 bit)
         * IBM AIX 7.10
         *
         */
        return &m_vData.front();  --> This works on windows, redhat, solaris 10, aix
}

/// Main class
int main() {
        // Vector of data
        vector<unsigned char> vData;

        // Add data onto the vector
        vData.push_back('a');
        vData.push_back('b');
        vData.push_back('c');

        // Create an instance from the vector of data given
        CData oData(vData);

        // Get the data from the instance
        size_t nSize(0);
        cout << "Data:" << oData.Data(nSize) << endl;

        return 0;
}

Output:
Data:abc