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

时间:2017-03-13 19:21:58

标签: c++ const stdvector

为C库编写C ++包装器。在库中有一个函数接受缓冲区unsigned char *。自从使用C ++以来,我将我的实际缓冲区存储在std::vector<char>中,而且,在包装器类中我还添加了const,因为所讨论的缓冲区是一个输入缓冲区,它不会被修改。但是我的代码没有编译,演示:

#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有什么问题?如果我从consts移除const std::vector<char> s(10);它可以正常工作,但我更喜欢这样。

3 个答案:

答案 0 :(得分:7)

您必须const_cast删除常量,然后reinterpret_castchar *投射到unsigned char *

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

注意:但是请记住,const_cast只有在您投射最初为非const的变量时才是安全的。请参阅this回答。

答案 1 :(得分:1)

您的错误是因为您将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保持为{{1} }}

答案 2 :(得分:0)

分享我的经验,因为我在跨平台实施期间也遇到了同样的问题。上述方法在Windows和Linux(Redhat)上运行良好,但在Solaris 10和IBM AIX上没有。

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

这是一种使用矢量数据'const'的方法,它可以在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