【问题标题】:MemCpy on a vector of structs结构向量上的 MemCpy
【发布时间】:2013-09-19 17:22:50
【问题描述】:

我已经使用 MapVirtualFile 在 Window 下使用 C++ VS2010 映射文件。 虚无是

  void*                   m_pVoiceData;

我现在想用数据填充结构向量。

结构是

struct udtPitchmark
{
    unsigned long ByteStart;
    unsigned long ByteCount;
    unsigned long F0;
};

struct udtPitchmarks
{
    vector<udtPitchmark>Pitchmarks;
};

我一直在用

void clsMapping::FeedPitchmarksFromMap(udtPitchmarks &uAudioInfo,unsigned long int uBytePos)
{

    unsigned int iCountPM;
    memcpy(&iCountPM, &((char*)(m_pVoiceData))[uBytePos],sizeof(unsigned long));

    uAudioInfo.Pitchmarks.resize(iCountPM);

    for (unsigned int i=0;i<iCountPM;i++)
    {
        iBytePos+=sizeof(unsigned long);
        unsigned long int iByteStart;
        memcpy(&iByteStart, &((char*)(m_pVoiceData))[iBytePos],4);

        iBytePos+=sizeof(unsigned long);
        unsigned long int iByteCount;
        memcpy(&iByteCount, &((char*)(m_pVoiceData))[iBytePos],4);

        iBytePos+=sizeof(unsigned long);
        unsigned int iF0;
        memcpy(&iF0, &((char*)(m_pVoiceData))[iBytePos],4);

        uAudioInfo.Pitchmarks[i].ByteStart =iByteStart;
        uAudioInfo.Pitchmarks[i].ByteCount =iByteCount;
        uAudioInfo.Pitchmarks[i].F0 =iF0;
    }
}

每个音高标记都涉及 3 个 memcpy。 但我希望我能一次阅读所有的音标。 但是我不知道该怎么做。

这样存储的结构:

vector<udtPitchmarks>::iterator it = nPitchmarks.Content().begin();
for (;it != nPitchmarks.Content().end(); ++it)
{
    unsigned int iCountPMs = it->Pitchmarks.size();
    fwrite(&iCountPMs,sizeof(unsigned int),1,outfile);

    vector<udtPitchmark>::iterator it2 = it->Pitchmarks.begin();
    for(;it2 != it->Pitchmarks.end(); ++it2)
    {
        fwrite(&it2->ByteStart,sizeof(unsigned long),1,outfile);
        fwrite(&it2->ByteCount,sizeof(unsigned long),1,outfile);
        fwrite(&it2->F0,sizeof(unsigned long),1,outfile);
    }
}

有人可以帮忙吗?

【问题讨论】:

  • 使用unsigned long[3],就可以一次性填写了。
  • 我编辑了我的帖子,现在所有 3 名成员都没有签名。假设有 10 个音高标记...您能发布一个示例,说明我如何一次完成所有这些标记吗?
  • 这样好吗? memcpy(&uAudioInfo.Pitchmarks[0],&((char*)(m_pVoiceData))[iBytePos],sizeof(unsigned long)*3*10);
  • 并非如此,您无法保证对象的内存是如何布局的。
  • 更好的办法是使用数组...

标签: c++ windows memcpy memory-mapped-files


【解决方案1】:

您可以一次读取整个 udtPitchmark 结构

m_pVoiceData = (char *)m_pVoiceData + sizeof(unsigned int); // size field

memcpy( &amp;uAudioInfo.Pitchmarks[i], (udtPitchmark *)m_pVoiceData + i, sizeof udtPitchmark );

或整个向量:

memcpy( &amp;uAudioInfo.Pitchmarks[0], (udtPitchmark *)m_pVoiceData, sizeof(udtPitchmark ) * iCountPM);

【讨论】:

  • 我试过 memcpy( &uAudioInfo.Pitchmarks[0], &((udtPitchmark *)(m_pVoiceData))[iBytePos], sizeof(udtPitchmark ) * iCountPM);现在,这接近您的建议,还包括结构所在的字节位置,但我在这里遇到了一个例外。你确定你是对的吗?
  • 我现在也发布了我存储数据的方式。
  • 哦,好的。然后我应该如何定义数据从哪里开始?
  • ((udtPitchmark *)(m_pVoiceData))[iBytePos] 表示 (m_pVoiceData + iBytePos * sizeof( udtPitchmark )),但 ((char *)(m_pVoiceData))[iBytePos] 表示 (m_pVoiceData + iBytePos * 大小(字符))。在我看来,你没有意识到这一点。在使用 m_pVoiceData 作为 udtPitchmark * 之前添加 4。而且你不需要 iBytePos。
  • 假设 m_pVoiceData 指向文件的开头。 uAudioInfo.Pitchmarks.resize(iCountPM); memcpy( &amp;uAudioInfo.Pitchmarks[0], (char *)m_pVoiceData + 1000, sizeof(udtPitchmark) * iCountPM )
【解决方案2】:

如果您将数据布置为数组,则可以一次性写入。访问器函数可以帮助您维护可读的界面:

struct Pitchmark
{
    unsigned long data[3];

    unsigned long & start() { return data[0]; }
    unsigned long & count() { return data[1]; }
    unsigned long & f0()    { return data[2]; }

    unsigned char * ptr() { return static_cast<unsigned char *>(data); }
};

Pitchmark pm;
memcpy(pm.ptr(), m_pVoiceData, sizeof pm.data);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-16
    • 1970-01-01
    • 2013-10-16
    相关资源
    最近更新 更多