简体   繁体   English

Pascal和Delphi阵列到C / C ++阵列

[英]Pascal and Delphi Arrays to C/C++ Arrays

In pascal and delphi, arrays have their lengths stored at some offset in memory from the array's pointer. 在pascal和delphi中,数组的长度存储在与数组指针相距一定距离的内存中。 I found that the following code works for me and it gets the length of an array: 我发现以下代码对我有用,它获取数组的长度:

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;

I translated the above code into C++ and it thus becomes: 我将上面的代码翻译成C ++,因此变成了:

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

int High(int* Arr)
{
    return *(Arr - sizeof(int));
}

Now assuming the above are equivalent to the Pascal/Delphi versions, how can I write a struct to represent a Pascal Array? 现在假设上面的内容等同于Pascal / Delphi版本,如何编写表示Pascal数组的结构?

In other words, how can I write a struct such that the following is true: 换句话说,如何编写满足以下条件的结构:

Length(SomeStructPointer) = SomeStructPointer->size

I tried the following: 我尝试了以下方法:

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;
}

In Pascal and Delphi, arrays have their lengths stored at some offset in memory from the array's pointer. 在Pascal和Delphi中,数组的长度存储在与数组指针相距一定距离的内存中。

This is not so. 事实并非如此。 The entire premise of your question is wrong. 您提出问题的全部前提是错误的。 The Delphi functions you present do not work in general. 您提供的Delphi函数通常无法正常工作。 They might work for dynamic arrays. 它们可能适用于动态数组。 But it is certainly not the case that you can pass an pointer to an array and be sure that the length is stored before it. 但是,肯定不是可以将指针传递给数组并确保将长度存储在数组之前的情况。

And in fact the Delphi code in the question does not even work for dynamic arrays. 实际上,问题中的Delphi代码甚至不适用于动态数组。 Your pointer arithmetic is all wrong. 您的指针算法全错了。 You read a value 16 bytes to the left rather than 4 bytes. 您读取的值向左16个字节而不是4个字节。 And you fail to check for nil. 而且您没有检查零。 So it's all a bit of a disaster really. 因此,这确实是一场灾难。

Moving on to your C++ code, you are reaping the result of this false premise. 转到C ++代码,您正在获得这种错误前提的结果。 You've allocated an array. 您已经分配了一个数组。 There's no reason to believe that the int to the left of the array holds the length. 没有理由相信数组左侧的int保持长度。 Your C++ code is also very broken. 您的C ++代码也很破损。 But there's little point attempting to fix it because it can never be fixed. 但是尝试修复它毫无意义,因为它永远无法修复。 The functions you define cannot be implemented. 您定义的功能无法实现。 It is simply not the case that an array is stored adjacent to a variable containing the length. 根本不是数组与包含长度的变量相邻存储。

What you are looking for in your C++ code is std::vector. 您在C ++代码中寻找的是std :: vector。 That offers first class support for obtaining the length of the container. 这为获得容器的长度提供了一流的支持。 Do not re-invent the wheel. 不要重新发明轮子。

If interop is your goal, then you need to use valid interop types. 如果互操作是您的目标,则需要使用有效的互操作类型。 And Delphi managed dynamic arrays do not qualify. 而且Delphi管理的动态数组不符合条件。 Use a pointer to an array, and a separately passed length. 使用指向数组的指针以及单独传递的长度。

Why? 为什么? I can see no good reason to do this. 我看不出这样做的充分理由。 Use idiomatic Pascal in Pascal, use idiomatic C++ in C++. 在Pascal中使用惯用的Pascal,在C ++中使用惯用的C ++。 Using sizeof like that also ignores padding, and so your results may vary from platform to platform. 像这样使用sizeof也会忽略填充,因此您的结果可能因平台而异。

If you want a size, store it in the struct. 如果需要大小,请将其存储在结构中。 If you want a non-member length function, just write one that works with the way you wrote the struct. 如果您想要一个非成员长度的函数,只需编写一个与您编写结构的方式兼容的函数即可。 Personally, I suggest using std::array if the size won't change and std::vector if it will. 就个人而言,我建议使用大小不变的std::array如果大小不变则使用std::vector If you absolutely need a non-member length function, try this: 如果您绝对需要非成员长度函数,请尝试以下操作:

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

That will work with both std::array and std::vector . 这将与std::arraystd::vector

PS: If you're doing this for "performance reasons", please profile your code and prove that there is a bottleneck before doing something that will become a maintenance hazard. PS:如果出于“性能原因”执行此操作,请先对代码进行概要分析并证明存在瓶颈,然后再执行可能会导致维护危险的操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM