如何在Delphi中执行C ++参数数组指针算法

蜜雪儿

在C ++中,您可以发送允许对数组进行指针运算的参数。我需要能够在Delphi 7项目中做到这一点。我尝试过这种方式,但是接收程序正在咳嗽。如果数组指针增加,c ^ [0]是否不应该位于新的增加位置?

第一个过程调用makect(),但首先通过增加指针将指针移至数组中较高的内存位置。但是,第二个过程在设置为数组指针位置0时不喜欢它。(当然,可能还有其他问题,但是我想知道自己是否正确执行了此操作)。

为清楚起见,此处列出的类型

type
  Pflt = ^flt;
  flt = double;

  Pflt_arr = ^flt_arr;
  flt_arr = array of flt;

  Pint_arr = ^int_arr;
  int_arr = array of integer;

constructor

constructor TRefT.Create(const length:integer);
begin
  len := length;
  SetLength(_ip, 2 + (1 shl trunc(ln(length / 4.0) / ln(2.0) + 0.5) shr 1) );
  _ip[0] := 0;
  SetLength(_w, length shr 1);
end;


procedure TRefT.CF(buff: pflt_arr);
begin
  rdft(len, 1, buff, @_ip, @_w);
end;

呼叫程序

procedure TRefT.rdft(n:integer; isgn:integer; a:Pflt_arr; ip:Pint_arr; w:Pflt_arr);
var nw, nc: integer;
xi: flt;
begin
 nw := ip^[0];
 nc := ip^[1];
 if n > (nc shl 2) then
 begin
  nc := n shr 2;
  inc(w, nw);       <--attempt at pointer arithmetic
  makect(nc, ip, w); <-- C++ version is makect(nc, ip, w + nw);
 end;
end;

接收程序(带有递增数组);

procedure TRefT.makect(nc:integer; ip:Pint_arr; c:Pflt_arr);
var j, nch: integer;
  delta: flt;
begin
ip^[1] := nc;
if nc > 1 then
 begin
    nch := nc shr 1;
    delta := arctan(1.0) / nch;
    c^[0] := cos(delta * nch);  <-- coughs here!
    c^[nch] := 0.5 * c^[0];
    for j := 1 to nch do
     begin
        c^[j] := 0.5 * cos(delta * j);
        c^[nc - j] := 0.5 * sin(delta * j);
     end;
 end;
end;
戴维·赫弗南

您的代码不正确。您有一个额外的,错误的间接级别。您需要的是指向的静态数组的Double指针而不是指向的动态数组的指针Double

请记住,动态数组是作为指向数组第一个元素的指针实现的。因此,就间接而言,您的类型等于指向标量指针的指针。

一种进行方式是声明这样的类型

type
  Pflt_arr = ^Tflt_arr;
  Tflt_arr = array [0..0] of flt;

  Pint_arr = ^Tint_arr;
  Tint_arr = array [0..0] of Integer;

并确保对此代码禁用更改检查。

这将允许您编写:

a^[i]

whena是类型Pflt_array

而且,如果您写:

inc(a, n);

然后它会递增地址,an*sizeof(a^)这是n*sizeof(Tflt_array)这是n*sizeof(flt)*Length(a^))这是n*sizeof(flt)这正是你想要的。

当您提供一个常量表达式作为索引时,这种方法会崩溃。按照这一行:

nc := ip^[1];

在这里,编译器将对象1不在范围内0..0因此,您不能同时拥有这两种方式。

在这种情况下,您似乎需要破解的前两个元素ip您可以这样做:

type
  Phuge_int_arr = ^Thuge_int_arr; 
  Thuge_int_arr = array [0..(MaxInt div sizeof(Integer))-1] of Integer;

然后写:

nc := Phuge_int_arr(ip)^[1];

感觉有点混乱。


另一种方法是编写这样的类型:

type
  Pflt_arr = ^Tflt_arr;
  Tflt_arr = array [0..(MaxInt div sizeof(flt))-1] of flt;

这对于所有索引方案都适用,并且可以使范围检查保持启用状态。但这使指针递增更加困难。现在您必须编写:

inc(Pflt(a), n);

总而言之,后一种方法可能是两种弊端中较小的一种。


声明实际存储的代码仍应使用动态数组SetLength等。当您需要Pflt_arrayPint_array强制转换动态数组时:

Pflt_array(dyn_array)

这是可行的,因为动态数组被实现为指向数组第一个元素的指针。


使用该0..0变体,您的代码如下所示:

type
  Pflt = ^flt;
  flt = Double;

  Pflt_arr = ^Tflt_arr;
  Tflt_arr = array [0..0] of flt;

  Pint_arr = ^Tint_arr;
  Tint_arr = array [0..0] of Integer;

  Phuge_int_arr = ^Thuge_int_arr; 
  Thuge_int_arr = array [0..(MaxInt div sizeof(Integer))-1] of Integer;

....

constructor TRefT.Create(const length:integer);
begin
  len := length;
  SetLength(_ip, 2 + (1 shl trunc(ln(length / 4.0) / ln(2.0) + 0.5) shr 1) );
  SetLength(_w, length shr 1);
end;

procedure TRefT.CF(buff: pflt_arr);
begin
  rdft(len, 1, buff, Pint_arr(_ip), Pflt_arr(_w));
end;

procedure TRefT.rdft(n:integer; isgn:integer; a:Pflt_arr; ip:Pint_arr; w:Pflt_arr);
var nw, nc: integer;
    xi: flt;
begin
  nw := Phuge_int_arr(ip)^[0];
  nc := Phuge_int_arr(ip)^[1];
  if n > (nc shl 2) then
  begin
    nc := n shr 2;
    inc(w, nw);
    makect(nc, ip, w);
  end;
end;

procedure TRefT.makect(nc:integer; ip:Pint_arr; c:Pflt_arr);
var j, nch: integer;
    delta: flt;
begin
  Phuge_int_arr(ip)^[1] := nc;
  if nc > 1 then
  begin
    nch := nc shr 1;
    delta := arctan(1.0) / nch;
    c^[0] := cos(delta * nch);
    c^[nch] := 0.5 * c^[0];
    for j := 1 to nch do
    begin
      c^[j] := 0.5 * cos(delta * j);
      c^[nc - j] := 0.5 * sin(delta * j);
    end;
  end;
end;

或使用的替代方法0..(MaxInt div sizeof(scalar))-1如下所示:

type
  Pflt = ^flt;
  flt = Double;

  Pflt_arr = ^Tflt_arr;
  Tflt_arr = array [0..(MaxInt div sizeof(flt))-1] of flt;

  Pint_arr = ^Tint_arr;
  Tint_arr = array [0..(MaxInt div sizeof(Integer))-1] of Integer;

....

constructor TRefT.Create(const length:integer);
begin
  len := length;
  SetLength(_ip, 2 + (1 shl trunc(ln(length / 4.0) / ln(2.0) + 0.5) shr 1) );
  SetLength(_w, length shr 1);
end;

procedure TRefT.CF(buff: pflt_arr);
begin
  rdft(len, 1, buff, Pint_arr(_ip), Pflt_arr(_w));
end;

procedure TRefT.rdft(n:integer; isgn:integer; a:Pflt_arr; ip:Pint_arr; w:Pflt_arr);
var nw, nc: integer;
    xi: flt;
begin
  nw := ip^[0];
  nc := ip^[1];
  if n > (nc shl 2) then
  begin
    nc := n shr 2;
    inc(Pflt(w), nw);
    makect(nc, ip, w);
  end;
end;

procedure TRefT.makect(nc:integer; ip:Pint_arr; c:Pflt_arr);
var j, nch: integer;
    delta: flt;
begin
  ip^[1] := nc;
  if nc > 1 then
  begin
    nch := nc shr 1;
    delta := arctan(1.0) / nch;
    c^[0] := cos(delta * nch);
    c^[nch] := 0.5 * c^[0];
    for j := 1 to nch do
    begin
      c^[j] := 0.5 * cos(delta * j);
      c^[nc - j] := 0.5 * sin(delta * j);
    end;
  end;
end;

随便你!


FWIW,为清晰起见,在移植此代码时,您可能会借此机会将shl 2andshr 2运算更改为算术运算。

您可能不知道的选项根本没有翻译。将原始.c文件编译为对象,然后使用静态链接它们$LINK

最后的评论是,您被如此古老的Delphi所困扰,真是太可惜了。现代版本具有$POINTERMATH编译器选项。这允许C风格的指针算术和对标量变量的纯指针进行索引。这种移植任务的巨大福音。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

在c中的参数数组

来自分类Dev

Verilog中的参数数组

来自分类Dev

在参数数组中传递整数数组

来自分类Dev

如何在nodejs中接受body中的参数数组

来自分类Dev

如何在C中执行参数解析?

来自分类Dev

C ++中的指针数组排序算法

来自分类Dev

如何在Verilog中初始化参数数组

来自分类Dev

如何在脚本的rsync调用中添加参数数组?

来自分类Dev

如何在Verilog中初始化参数数组?

来自分类Dev

如何迭代多个参数数组

来自分类Dev

在perl中获取参数函数数组

来自分类Dev

C#函数参数数组与列表

来自分类Dev

如何基于输入参数数组在函数内部执行函数?

来自分类Dev

如何在C中制作字符串参数数组

来自分类Dev

找到实数数组中每个元素的频率最快的算法?

来自分类Dev

找到实数数组中每个元素的频率最快的算法?

来自分类Dev

C数组/指针参数转换

来自分类Dev

整数数组初始化的C ++指针

来自分类Dev

如何在Android中使用Volley发送参数数组

来自分类Dev

如何在一行代码中初始化指向整数数组的指针?

来自分类Dev

将assoc中的参数数组转换为数组

来自分类Dev

如何从命令参数数组中删除提到的用户?

来自分类Dev

C#如何使扩展接受IEnumerable而不是参数数组

来自分类Dev

指针数组作为c函数中的参数

来自分类Dev

C中函数数组的参数传递/返回,

来自分类Dev

Delphi-如何将通用参数传递给接受const参数数组的函数

来自分类Dev

如何在c中填充指针数组

来自分类Dev

如何在C ++中删除指针数组?

来自分类Dev

如何调用以指针数组为参数的函数?在C中