Delphi 的内存操作函数(1): 给字符指针分配内存
马上能想到的函数有:
GetMem
AllocMem
ReallocMem
FreeMem GetMemory
ReallocMemory
FreeMemory New
Dispose NewStr
DisposeStr StrNew
StrAlloc
StrDispose GlobalAllocPtr
GlobalFreePtr WideStrAlloc
AnsiStrAlloc
StrDispose Move
MoveMemory
CopyMemory
ZeroMemory
FillMemory
FillChar StrBufSize
给字符指针(PChar、PWideChar、PAnsiChar)分配内存, 最佳选择是: StrAlloc.
StrAlloc 虽然最终也是调用了 GetMem, 但 StrAlloc 会在指针前面添加 Delphi 需要的 4 个管理字节(记录长度).
StrAlloc 分配的内存, 用 StrDispose 释放, 用 StrBufSize 获取大小.
用 FreeMem 释放可以吗? 这样会少释放 4 个字节.
这种类型的指针一般用于 API 函数的参数, 譬如获取窗口标题:
var
p: PChar;
begin
p := StrAlloc();
GetWindowText(Handle, p, StrBufSize(p));
ShowMessage(p); {Form1}
StrDispose(p);
end;
StrAlloc 根据不同的参数(PWideChar、PAnsiChar)分别重载调用了 WideStrAlloc、AnsiStrAlloc, 所以我们也可以直接使用这两个函数(这也需要用 StrDispose 释放), 不过使用它们的必要性不大; 用 StrAlloc 指定好参数类型即可.
给字符指针分配内存其他方法也挺方便, 譬如:
//获取 WINDOWS 所在目录
var
buf: array[..MAX_PATH] of Char;
begin
GetWindowsDirectory(buf, Length(buf));
ShowMessage(buf); {C:\WINDOWS}
end;
数组的内存不是我们自己申请的, 系统会自动释放; 记住: 只要是手动申请的内存一定要手动释放.
我们给字符指针申请内存主要是为了在 API 中接受数据, 如果我们要直接赋给常量值, 系统会自动分配内存的, 譬如:
var
p: PChar;
begin
p := '万一的 Delphi 博客';
ShowMessage(p); {万一的 Delphi 博客}
end;
当然我们也可以用这种办法申请内存, 就是笨了点, 譬如:
//获取系统目录
var
p: PChar;
begin
p := PChar(StringOfChar(Char(), )); {反复一个空字符 256 次成一个字符串, 然后转为 PChar}
GetSystemDirectory(p, StrBufSize(p));
ShowMessage(p); {C:\WINDOWS\system32}
end;
如果在 API 函数需要的字符指针是为了输入, 当然也不需要申请内存, 譬如:
//设置窗口标题
var
p: PChar;
begin
p := '窗口新标题';
SetWindowText(Handle, p);
end; //也可以直接给常量
begin
MessageBox(Handle, '提示信息', '标题', MB_OK);
end; //如果是给字符串的变量或常量, 则需要转换一下
var
str: string;
begin
str := '万一的 Delphi 博客';
TextOut(Canvas.Handle, , , PChar(str), Length(str));
{在窗体上输出文字, 此代码不能在 OnCreate 事件中}
end;
跑题了...到现在已用到了 StrAlloc、StrDispose、WideStrAlloc、AnsiStrAlloc、StrBufSize 几个函数.
还有 NewStr、DisposeStr、StrNew、StrDispose 也貌似有点关系.
先说 NewStr 和 DisposeStr(它们是一对);
NewStr 是根据 AnsiString 再新建一个 PAnsiString, 不过这是为兼容而存在的, Delphi 已不提倡使用了.
不再提倡使用的函数都缀以 deprecated 标识, 并在代码提示中用灰色显示.
其实用 @ 即可获取字符串指针, 当然根本用不着它们.
还有个 StrNew; StrNew 可以再制一个相同的字符指针, 譬如:
var
p1,p2: PChar;
begin
p1 := 'Delphi'; p2 := StrNew(p1);
ShowMessageFmt('%s, %s', [p1, p2]); {Delphi, Delphi} p1 := '2009';
ShowMessageFmt('%s, %s', [p1, p2]); {2009, Delphi} StrDispose(p2); {释放自己申请的}
end;
不过 StrNew 存在的意义也不大, 我们可以更简单地完成上面的操作:
var
p1,p2: PChar;
begin
p1 := 'Delphi';
p2 := p1;
ShowMessageFmt('%s, %s', [p1, p2]); {Delphi, Delphi}
p1 := '2009';
ShowMessageFmt('%s, %s', [p1, p2]); {2009, Delphi}
end;
说来说去, 好像只有 StrAlloc 是我们值得我们记忆的?
还有一对非常重要的相关函数: GlobalAllocPtr、GlobalFreePtr; 它们的功能是上面这些都不可替代的!
GlobalAllocPtr 和 GlobalFreePtr 是对系统函数: GlobalAlloc、GlobalFree 的简化, 之所以说它们重要, 只是因为它们可以跨进程操作; 不过 GlobalAllocPtr 是给无类型指针(Pointer)分配内存, 当然就不仅仅用于字符指针了. 还是到后面专题再做例子吧.
Delphi 的内存操作函数(1): 给字符指针分配内存的更多相关文章
- Delphi 的内存操作函数(1): 给字符指针分配内存( 给字符指针(PChar、PWideChar、PAnsiChar)分配内存最佳的选择是StrAlloc。分配内存的时候会对字符串进行初始化)
马上能想到的函数有: GetMem AllocMem ReallocMem FreeMem GetMemory ReallocMemory FreeMemory New Dispose NewStr ...
- Delphi 的内存操作函数(2): 给数组指针分配内存
静态数组, 在声明时就分配好内存了, 譬如: var arr1: ..] of Char; arr2: ..] of Integer; begin ShowMessageFmt('数组大小 ...
- delphi 给字符指针分配内存
今天,对接第三方dll的时候出现如下问题: 接口声明如下: long BL_tradeBalance (char *MerchantNumber,char *PosId,char *OperatorN ...
- Delphi中复制带有String的记录结构时不能使用Move之类的内存操作函数
请看下面的代码: program TestRecord; {$APPTYPE CONSOLE} uses SysUtils, Math; type TRecordA = record Na ...
- 内存操作函数memmove,memcpy,memset
通过字符串的学习,我们知道字符串操作函数的操作对象是字符串,并且它的结束标志是结束符\0,当然这个说的是不 受限制的字符串函数.然而当我们想要将一段内存的数据复制到另一块内存时,我们不能使用字符串操作 ...
- C语言中内存操作函数
一.malloc/calloc 名称: Malloc/calloc 功能: 动态内存分配函数 头文件: #include <stdlib.h> 函数原形: void *malloc(s ...
- c++ void,内存操作函数
void的含义 void的字面意思是“无类型”, void * 则为“无类型指针”, void * 可以指向任何类型的数据 void几乎只有“注释”和限制程序的作用,因为从来没有人会定义一个void变 ...
- c#读写共享内存操作函数封装
原文 c#读写共享内存操作函数封装 c#共享内存操作相对c++共享内存操作来说原理是一样,但是c#会显得有点复杂. 现把昨天封装的读写共享内存封装的函数记录下来,一方面希望给需要这块的有点帮助,另一方 ...
- 【转】C内存操作函数
一.malloc/calloc 名称: Malloc/calloc 功能: 动态内存分配函数 头文件: #include <stdlib.h> 函数原形: void *malloc(si ...
随机推荐
- 【数论 dp】2048
考场上一个DFS优化乱加就对了一个无解的点 题目描述 给定一个长度为 n 的数列,在这个数列中选取一个子序列使得这个子序列中的数能合出2048 对于合并操作,可以选择这个序列中的任意两个数进行合并,当 ...
- Juqyer:$.ajax()方法详解
Jquery中的ajax方法参数总是记不住,这里记录一下. 最常用的属性是:url.data 1.url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址. 2.type: 要求为S ...
- python--基础数据类型的补充与深浅copy
一 . join的用法 lst =['吴彦祖','谢霆锋','刘德华'] s = '_'.join(lst) print(s) # 吴彦祖_谢霆锋_刘德华 # join() "*" ...
- Python之路-基础数据类型之字典 集合
字典的定义-dict 字典(dict)是python中唯⼀的⼀个映射类型.他是以{ }括起来的键值对组成,字典是无序的,key是不可修改的.dic = {1:'好',2:'美',3:'啊'} 字典的操 ...
- module_param
该宏定义在include/linux/moduleparam.h中 #define ___module_cat(a,b) __mod_ ## a ## b #define __module_cat(a ...
- 流编辑器sed知识点总结
sed(流文本编辑器) 每次读取一行到模式空间中, 修改的sed模式空间中的内容,并不会修改源文件, 继而输出模式空间的内容, 最后删除模式空间中的内容. sed [O ...
- mysql复制延迟排查
今天收到报警,提示从库延时,首先当然是上去查看情况,首先查看机器负载,如下: 可以看到使用cpu已经100%,io没有等待.那么查看mysql是什么情况,执行show processlist没有发现任 ...
- .NET中常见的加解密方式
在互联网普及的初期,人们更关注单纯的连接性,以不受任何限制地建立互联网为最终目的.正如事情都具有两面性,互联网的便捷性给人们带来了负面问题,计算机病毒的侵害.信息泄露.网络欺诈等利用互联网的犯罪行为日 ...
- ASP.NET MVC 通用角色权限管理系统
RightControl 介绍 .NET 通用后台角色权限管理系统,已完成.项目地址:http://106.14.77.184/Admin/Login 码云地址:https://gitee.com/L ...
- git删除本地所有的更改
删除本地所有为暂存的修改: git checkout -f 如果有修改以及加入暂存区的话 那么 使用如下命令: git reset --hard git clean -xdf