• Delphi 无类型参数传递动态数组和静态数组


    前几天发现的一个相关的问题,总结了下,备忘:

    相关几个函数声明:
    procedure FillChar(var X; Count: Integer; Value: Byte);
    procedure  CopyMemory(Destination: Pointer; Source: Pointer; Length: DWORD);
    function THandleStream.Write(const Buffer; Count: Longint): Longint;

    测试代码:

    测试代码
    procedure TForm1.btn1Click(Sender: TObject);
    var
    verifyMsg :
    array[0..48] of Char; //定长数组
    signedLen : Integer;
    verfyFile : TFileStream;
    str :
    string;
    len : Integer;
    begin
    len :
    = 48;
    str :
    = 'hello world';

    FillChar(verifyMsg[
    0], len, 0);
    // OK
    // FillChar(verifyMsg, len, 0);

    CopyMemory(@verifyMsg[
    0], PChar(@str[1]), Length(str)); //要从str[1] 开始copy
    // OK
    // CopyMemory(@verifyMsg, Pointer(str), Length(str)); //str pointer pchar都可以
    // OK
    // CopyMemory(@verifyMsg, @str[1], Length(str)); //要从str[1] 开始copy

    verfyFile :
    = TFileStream.Create('c:\\test.data', fmCreate or fmShareDenyRead);

    // 方法1 Ok
    verfyFile.Write(verifyMsg[
    0], Length(verifyMsg));
    // 方法 2 OK
    // verfyFile.Write(PChar(@verifyMsg[0])^, Length(verifyMsg));
    // 方法 3 OK
    // verfyFile.Write(verifyMsg, Length(verifyMsg));

    // 测试写入字符串
    // 方法1 OK
    // verfyFile.write(PChar(str)^,length(str));
    // 方法 2 wrong
    // 写入内容是错误的 可能是str的内部结构导致
    // verfyFile.write(str, length(str));
    // 方法 3 OK
    // verfyFile.write(str[1], length(str));
    // 方法 4 OK
    // verfyFile.write(Pointer(str)^,length(str));

    freeAndNil(verfyFile);
    end;

    procedure TForm1.btn2Click(Sender: TObject);
    var
    verifyMsg :
    array of Char; //动态数组
    signedLen : Integer;
    verfyFile : TFileStream;
    str :
    string;
    len : Integer;
    begin
    len :
    = 48;
    str :
    = 'hello world';
    SetLength(verifyMsg, len);

    // Error FillChar 参数不是指针,如下这行所以是错的.
    // FillChar(verifyMsg, len, 0);
    FillChar(verifyMsg[
    0], len, 0);

    // OK 接收参数是指针
    CopyMemory(@verifyMsg[
    0], @str[1], Length(str));
    // 要从str[1] 开始copy
    // CopyMemory(verifyMsg, PChar(@str[1]), Length(str));
    verfyFile :
    = TFileStream.Create('c:\\test2.data', fmCreate or fmShareDenyRead);

    // 方法 1 OK 接收参数是无参类型
    // verfyFile.Write(PChar(@verifyMsg[0])^, Length(verifyMsg));
    // 方法 2 OK 接收参数是无参类型
    verfyFile.Write(verifyMsg[
    0], Length(verifyMsg));

    freeAndNil(verfyFile);
    end;

    原因和结论:

    1.定长数组A就是一个变量,A和A[0], @A=@A[0]
    动态数组B就是一个指针,B是数组的首地址.B=@B[0]
    2.普通参数按值传递,常量参数和变量参数都是按地址传递的 ,无类型参数只能是常量或变量参数,都是按地址传递
    3.Best Practise:在用数组作参数的时,不管静态动态一率从0开始,要求传无类型参数的时候一率用arr[0]是个好习惯。写成 arr[Low(arr)] 最好.

    参考:
    Delphi - 数组 详解
    http://www.cnblogs.com/huangjacky/archive/2009/12/21/1628833.html
    诡异的动态数组问题
    http://bbs.2ccc.com/topic.asp?topicid=358558
    关于指针和过程/函数的无类型 var 参数的问题。
    http://www.delphibbs.com/delphibbs/dispq.asp?lid=1938519

  • 相关阅读:
    java实现孪生素数
    java实现孪生素数
    java实现孪生素数
    java实现孪生素数
    java实现孪生素数
    java实现连续数的公倍数
    java实现连续数的公倍数
    mysql千万级数据量根据索引优化查询速度
    MySQL特异功能之:Impossible WHERE noticed after reading const tables
    MySQL:浅析 Impossible WHERE noticed after reading const tables
  • 原文地址:https://www.cnblogs.com/solo/p/1892708.html
Copyright © 2020-2023  润新知