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);
这是对结构化数据执行一种二进制序列化。查看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上工作。