c++内存与c#等价

本文关键字:等价 内存 c++ | 更新日期: 2023-09-27 17:49:57

我实际上是一个java开发人员,但是对于一个休闲项目,我正在尝试将一个库从c++转换为c#。我有一点c++背景,但这段代码让我很困惑

    long hfzWriteHeader(hfzFile* fs, hfzHeader& fh) {
        // copy header into buffer
        char HeaderBuf[28];
        long HeaderBufPos = 0;
        sprintf(HeaderBuf+HeaderBufPos, "HF2"); HeaderBufPos+=4;
        hfzMemcpy(HeaderBuf+HeaderBufPos, &(fh.FileVersionNo), 2); HeaderBufPos+=2;
        hfzMemcpy(HeaderBuf+HeaderBufPos, &(fh.nx), 4); HeaderBufPos+=4;
        hfzMemcpy(HeaderBuf+HeaderBufPos, &(fh.ny), 4); HeaderBufPos+=4;
        hfzMemcpy(HeaderBuf+HeaderBufPos, &(fh.TileSize), 2); HeaderBufPos+=2;
        hfzMemcpy(HeaderBuf+HeaderBufPos, &(fh.Precis), 4); HeaderBufPos+=4;
        hfzMemcpy(HeaderBuf+HeaderBufPos, &(fh.HorizScale), 4); HeaderBufPos+=4;
        // put extended header into a buffer
        char* pExtHeaderData = 0;
        long rval = hfzHeader_EncodeExtHeaderBuf(fh, &pExtHeaderData);
        if(rval<0) return rval;
        // now write in header length of ext header
        hfzMemcpy(HeaderBuf+HeaderBufPos, &(fh.ExtHeaderLength), 4);    
            HeaderBufPos+=4;
        // swap byte order if required (files use little endian)
        if(LIBHFZ_BYTEORDER_BIGENDIAN==hfzByteOrder) {
        HeaderBufPos = 4; // skip "HF2'0" string
           hfzByteSwap(HeaderBuf+HeaderBufPos, 2); HeaderBufPos+=2; // FileVersionNo
           hfzByteSwap(HeaderBuf+HeaderBufPos, 4); HeaderBufPos+=4; // nx
           hfzByteSwap(HeaderBuf+HeaderBufPos, 4); HeaderBufPos+=4; // ny
           hfzByteSwap(HeaderBuf+HeaderBufPos, 2); HeaderBufPos+=2; // TileSize
           hfzByteSwap(HeaderBuf+HeaderBufPos, 4); HeaderBufPos+=4; // Precis
           hfzByteSwap(HeaderBuf+HeaderBufPos, 4); HeaderBufPos+=4; // HorizScale
           hfzByteSwap(HeaderBuf+HeaderBufPos, 4); HeaderBufPos+=4; // ExtHeaderLength
       }
   // write header
   if(28!=hfzWrite(fs, HeaderBuf, 28)) 
       return LIBHFZ_ERROR_WRITE_HEADER_FAILED;
// write extended header
   if(pExtHeaderData) {
       if(fh.ExtHeaderLength!=hfzWrite(fs, pExtHeaderData, fh.ExtHeaderLength)) {
           hfzFree(pExtHeaderData);
           return LIBHFZ_ERROR_WRITE_EXTHEAD_FAILED;
       }
       hfzFree(pExtHeaderData);
   }
   return LIBHFZ_STATUS_OK;
   }

我相信它试图在内存中建立一个字符数组(字符串?),以便他可以稍后将其写入二进制文件。这是文件类型的头部分。在java中,我可能只会使用字符串构建器,然后追加。然而,我确实相信一些字节操作正在进行,字符串的每个部分都是相同的字节数,但我想知道fh。Nx是空的如果空的值是1,结果会是什么?是"1"还是"0001"?这就是我不明白的地方。

感谢任何对我C语言知识不足的帮助或启发

似乎把整个函数放在这里会更好,而不是它的一部分,因为稍后会发生一些与BIGENDIAN情况。很抱歉,在stackoverflow上正确使用格式是很麻烦的。

========= 初步的结果 ==============

所以我最终使用John Skeet的类来处理端序,并想出了这个…我只是想知道我是不是做错了。我是基于c++的方法结构重写的,但是很多方法都是低级别的,它们在更高级别的c#中是可用的……现在我记得为什么我选择Java而不是c了。我很快就被所有的指针和内存处理搞混了!

仅供参考,这是我试图编写和转换库的文件格式:http://www.bundysoft.com/docs/doku.php?id=l3dt:格式:规格:hf2

    // copy header into buffer
    MiscUtil.Conversion.EndianBitConverter endian = MiscUtil.Conversion.EndianBitConverter.Big;
    if (BitConverter.IsLittleEndian)
    {
        endian = MiscUtil.Conversion.EndianBitConverter.Little;
    }
    MemoryStream buffer = new MemoryStream();
    EndianBinaryWriter writer = new EndianBinaryWriter(endian, buffer);
    writer.Write("HF2");
    writer.Write(fh.FileVersionNo);
    writer.Write(fh.nx);
    writer.Write(fh.ny);
    writer.Write(fh.TileSize);
    writer.Write(fh.Precis);
    writer.Write(fh.HorizScale);

c++内存与c#等价

这是对结构化数据执行一种二进制序列化。查看BinaryWriter以获得。net中的类似功能。这可以附加到任何流,但如果你想使用字节数组作为后备存储(如在C代码中),可以使用MemoryStream。

还要注意(正如另一个海报提到的),您可能必须注意尾端性和其他特定于平台的问题,至少假设您希望与C程序二进制兼容。在不知道原始程序使用的平台以及如何与之交互操作(如果有的话)的情况下,很难说得更多。例如,数据是否保存到您希望能够加载的文件中?


更新:

根据您的编辑,看起来原始代码是尾端感知的。你可以使用BitConverter。IsLittleEndian来检查你的平台的端进性,并在你的c#代码中对你的字节数组进行等效的交换调整。

如果你知道你在Windows上运行并且不想担心跨平台支持,你可以假设BinaryWriter是Little Endian(实际上,它可能在Mono中也是Little Endian,甚至在Big Endian平台上,但我不确定。)如果您希望安全起见,您可以查看Jon Skeet编写的一个实用程序类,它处理必要的转换。

取决于大小(短)和机器是大端还是小端。Sizeof (short)可能是2(但没有什么可以保证),给出:

  • big-endian: 00 01 xx xx
  • little-endian: 01 00 xx xx

其中xx是一些随机的垃圾。00表示值为0x00的字节;01是一个值为0x01的字节。

为什么代码复制四个字节是一个谜…

整个事情是可怕的:它导致特定于平台和(我相当确定,但不要引用我的话)未定义的行为。

更新:考虑到OP的更新(变量是长而不是短,以及处理端序的额外代码),我的最后一句话现在有点不合理了。

[DllImport("kernel32.dll")]
private static extern void RtlMoveMemory(IntPtr dest, IntPtr src, int byteCount);

这是一个与指针一起使用的真正的内存拷贝,并且应该在所有版本的Windows上工作。