在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;
字符串
我把上面的代码翻译成C++,它就变成了:
int Length(int* Arr)
{
int* Ptr = (Arr - sizeof(int));
return *reinterpret_cast<char*>(Ptr) + 1;
}
int High(int* Arr)
{
return *(Arr - sizeof(int));
}
型
现在假设上面的是等价于Pascal/ Delphi 版本,我如何写一个结构来表示Pascal数组?
换句话说,我如何编写一个结构体,使以下内容为真:
第一个月
我尝试了以下方法:
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;
}
型
3条答案
按热度按时间gdx19jrr1#
为什么?为什么?我看不出有什么好的理由这么做。在Pascal中使用惯用Pascal,在C中使用惯用C。像这样使用sizeof也会忽略填充,所以你的结果可能会因平台而异。
如果你想要一个大小,将其存储在结构中。如果你想要一个非成员长度函数,只需编写一个与你编写结构的方式一起工作的函数。我个人建议,如果大小不会改变,则使用
std::array
,如果大小会改变,则使用std::vector
。如果你绝对需要一个非成员长度函数,请尝试以下操作:字符串
这将适用于
std::array
和std::vector
。附言:如果您这样做是出于“性能原因”,请分析您的代码,并在执行将成为维护风险的操作之前证明存在瓶颈。
mftmpeh82#
在Pascal和 Delphi 中,数组的长度存储在内存中数组指针的某个偏移量处。
事实并非如此。你的问题的整个前提都是错误的。你给出的 Delphi 函数一般都不起作用。它们可能对动态数组起作用。但你可以传递一个指向数组的指针,并确保长度存储在它之前,这肯定是不可能的。
事实上,问题中的 Delphi 代码甚至不能处理动态数组。你的指针算法完全错误。你读取的值是向左16个字节,而不是4个字节。你无法检查nil。所以这真的有点像一场灾难。
接下来是C代码,你正在收获这个错误前提的结果。你已经分配了一个数组。没有理由相信数组左边的int拥有长度。你的C代码也是非常破碎的。但是尝试修复它没有什么意义,因为它永远无法修复。您定义的函数无法实现。数组存储的情况根本就不是这样与包含长度的变量相邻。
你在C++代码中寻找的是std::vector。它为获取容器的长度提供了一流的支持。不要重新发明轮子。
如果互操作是你的目标,那么你需要使用有效的互操作类型。而 Delphi 管理的动态数组不合格。使用一个指向数组的指针,和一个单独传递的长度。
bksxznpy3#
上面的每一个评论都是错误的,并且仍然错误地认为Pascal和 Delphi 没有在数据之前存储数组和字符串长度。
https://github.com/fpc/FPCSource/blob/main/rtl/inc/ustrings.inc#L39https://github.com/fpc/FPCSource/blob/main/rtl/inc/ustrings.inc#L203https://github.com/fpc/FPCSource/blob/main/rtl/inc/astrings.inc#L43
数组也是如此。在 Delphi 中也是如此。我检查过了。GCC有
regparm
调用约定,你也可以用它来调用Pascal/ Delphi 函数。字符串
使用方法:
型
Pascal和 Delphi 都能正确地看到字符串/数组及其大小。它们也能正确地释放它们。所以不需要导出C的创建和销毁函数来操作指针。