Pascal和Delphi数组到C/C++数组

Bra*_*don -1 c c++ arrays delphi pascalscript

在pascal和delphi中,数组的长度存储在数组指针的内存中的某个偏移处.我发现以下代码适用于我,它获取数组的长度:

type PInt = ^Integer; //pointer to integer.

Function Length(Arr: PInt): Integer;
var
  Ptr: PInt;
Begin
  Ptr := Arr - sizeof(Integer);
  Result := Ptr^ + 1;
End;

Function High(Arr: PInt): Integer;  //equivalent to length - 1.
Begin
  Result := (Arr - sizeof(Integer))^;
End;
Run Code Online (Sandbox Code Playgroud)

我将上面的代码翻译成C++,因此变为:

int Length(int* Arr)
{
  int* Ptr = (Arr - sizeof(int));
  return *reinterpret_cast<char*>(Ptr) + 1;
}

int High(int* Arr)
{
    return *(Arr - sizeof(int));
}
Run Code Online (Sandbox Code Playgroud)

现在假设上面的等价于Pascal/Delphi版本,我如何编写一个表示Pascal数组的结构?

换句话说,我如何编写一个结构,以便满足以下条件:

Length(SomeStructPointer) = SomeStructPointer->size

我尝试了以下方法:

typedef struct
{
    unsigned size;
    int* IntArray;
} PSArray;

int main()
{
    PSArray ps;
    ps.IntArray = new int[100];
    ps.size = 100;

    std::cout<<Length((int*) &ps); //should print 100 or the size member but it doesn't.

    delete[] ps.IntArray;
}
Run Code Online (Sandbox Code Playgroud)

Dav*_*nan 7

在Pascal和Delphi中,数组的长度存储在数组指针的内存偏移量中.

事实并非如此.你问题的整个前提是错误的.您提供的Delphi函数一般不起作用.它们可能适用于动态数组.但肯定不是你可以将指针传递给数组并确保长度存储在它之前.

事实上,问题中的Delphi代码甚至不适用于动态数组.你的指针算术都错了.您读取左侧16个字节而不是4个字节的值.你没有检查没有.所以这真的是一场灾难.

转到你的C++代码,你正在收获这个错误前提的结果.你已经分配了一个数组.没有理由相信数组左边的int保持长度.您的C++代码也非常破碎.但尝试修复它没有什么意义,因为它永远无法修复.您定义的功能无法实现.根本不是将数组存储在包含长度的变量附近的情况.

您在C++代码中寻找的是std :: vector.这为获得容器的长度提供了一流的支持.不要重新发明轮子.

如果interop是您的目标,那么您需要使用有效的互操作类型.并且Delphi管理的动态数组不符合条件.使用指向数组的指针和单独传递的长度.


Mar*_*ark 6

为什么?我认为没有充分理由这样做.在Pascal中使用惯用的Pascal,在C++中使用惯用的C++.使用像这样的sizeof也会忽略填充,因此您的结果可能因平台而异.

如果您想要一个大小,请将其存储在结构中.如果你想要一个非成员长度函数,只需编写一个与你编写结构的方式一致的函数.就个人而言,我建议使用,std::array如果尺寸不会改变,std::vector如果它会.如果您绝对需要非成员长度函数,请尝试以下方法:

template<typename T>
auto length(const T& t) -> decltype(t.size()) {
    return t.size();
}
Run Code Online (Sandbox Code Playgroud)

这将适用于std::arraystd::vector.

PS:如果你出于"性能原因"这样做,请描述你的代码并证明在做一些会成为维护危险的事情之前存在瓶颈.