来自:http://blog.163.com/kat_/blog/static/189284269201152513331999/

-------------------------------------------------------------------------------------

tring和Char数组都是一块内存, 其中存放连续的字符. string保存具体字符的内存对用户

是透明的, 由Delphi管理它的分配, 复制和释放, 用户不能干预(其实也可以, 不过是通过

非法途径). Char数组就不必说了吧?

PChar是一个指针, 它的大小只有32位. 定义时由Delphi自动填0. 要将PChar作为字符串

使用的话必须自己分配内存用完必须自己释放. PChar型字符串由#0表示字符串结尾

Delphi所提供的相关PChar字符串的操作都是判断#0来决定字符串的结尾的。

因为PChar是指针,所以它能指向任何地方(也就是说它不一定非要指向字符串不可).

把一个String赋值给PChar只是将String中保存具体字符串的内存的地址给 PChar

变量. 当然也可以把Char数组第一个元素的地址给PChar.

至于 哪个占用内存小, Char数组<PChar(指分配过字符串的)<string(除了具体字符串外

还 包含字符串长度)

如果空字符串那么PChar<String<array [0..n] of Char

从速度来说毫无疑问string最慢, 例如:

作为参数传递(非var调用时)给过程时string将整个字串的副本传递过去, PChar将指针

本身的副本传递过去(32位), Char数组和PChar一样, 传递的是第一个元素的地址副本.

不过就灵活性来说string最高, 而且Delphi支持的函数最多. 另外可以将String作为

Buffer使用(因为它当中可以包含字符0).

amo (2000-9-20 1:35:26)

----------------------------------------------------------------------------------

在Delphi2.0以后的版本中,

string分两种,

一种是与Pascal传统string相兼容,叫ShortString,

它的存储结构如下:

+---------------------+

| 1Byte |    字符串内容 |

+---------------------+

0         1 ......

其中第一个字节为字符串的长度。

所以ShortString所能包括的字符串长度不能大于255。

另一种是叫长字符串AnsiString,    它就是一个指向字符串的指针,不过具体的存储有些特别。

它的存储结构如下:

+-----------------------+

| 4B | 4B |    字符串内容 |

+-----------------------+

-8     -4     0    ......

其中,AnsiString指向字符串第一个字符,

在第一个字符的反方向第1到第4的4个字节表示字符串长度,第5到第8的4个字节表字符串被引用的次数。

pchar就是纯指向字符串(#0字符结尾)的指针,与C语言中的char *是一样的。

char数组也是指向字符串的指针,它与pchar的区别在于:

1.char数组(均指非动态数组)一旦定义好,它的长度就固定了;

2.char数组的地址是常量,不能另赋其它值,不能象pchar一样,

如: sPchar:pchar; sArray1,sArray2:array[0..80]of char;

sPChar:=sArray2; sPChar;=sArray1;

但不能sArray2:=sArray1;

char数组就相当于const char *

要说速度最快当然是纯指针操作的pchar与char数组最快啦

所谓占内存最少,效率更高,

不知老兄你想进行什么方面的应用,

一般对string,pchar或char数组,不用考虑这些。

对编程而言,如果在Delphi或C++Builder中使用,可尽量使用 AnsiString,

Borland公司对它已经进行了非常完美的内部处理,

使用非常方便。

如果涉及到Windows API或混合编程等,接口部分一般使用pchar。

char数组使用的比较少了,因为多数可以用char数组的地方,

现在比较流行的作法是定义一个ansistring, 再用setlength来设定它的长度。

lycwg (2001-1-12 11:53:20)

------------------------------------------------------------

三、字符串string 字符数组与指向字

  符串的指针pchar的区别与联系

  这3者的基本概念相同,但有一些非常细微的差别,在编程时稍不注意就会出错,需高度重视。

  1、使用指向字符串的指针,如果不是以0结尾,运行时就会出现错误。为了避免这种错误, 需要在字符串结尾人工加入0 即char(0),或用strpcopy函数在字符串结尾自动加0。

  例1: 指向字符串的指针,如果不是以0结尾,运行时会出现错误:

  {s[0]=3 s[1]='n' s[2]='e' s[3]='w'}

  var

  s:string;

p:pchar;

  begin

  s:='new';

  label1.caption:=s; {new}

 label2.caption:=intTostr(integer(s[0]));{3是字符串的长度}

  p:=@s[1];{不是以0结尾,莫用pchar型指针}

       label3.caption:=strpas(p); {运行时出现错误}

  end;

  例2:在字符串结尾人工加入0即char(0),可使用指向字符串的指针。

  {s[0]=4 s[1]='n' s[2]='e' s[3]='w' s[4]=0;}

  {p-->'new'}

  var

s:string;

p:pchar;

  begin

  p:=@s[1];

  s:='new'+char(0); {以0结尾,可用pchar型指针}

  label1.caption:=strpas(p); {new}

注意:

procedure    GetMem(var    P:    Pointer;    Size:    Integer);

//分配动态内存

function    StrPas(const    Str:    PChar):    string;

//将PChar转换为String

------------------------------------------------------csdn达人回复---------------------------------------------------------------

char,   array   of   char,   PChar都是简单类型,简单类型当然通用性好,这个很容易理解,只要保证内存布局一样就可以了,在这个前提下如果有必要可以采取手段欺骗编译器的强类型 检查。Delphi为什么提出string类型?肯定有它的道理。什么道理?用C的同志们都知道处理什么类型都没有处理字串类型费劲,Delphi作为如 此优秀的RAD工具自然要想办法解决这个问题。事实上,如果你能充分的理解string,你就会赞叹Delphi的精妙了。

处理字串时 候最恼人的问题之一就是内存的分配与释放,如果你用char数组(array   [0..l]   of   char等同于C中的char[l+1]),则内存被静态分配,这种情况主要用在定宽字符串中。但是对于最常见的变长字串可就费劲了。string解决这 个问题的手段是,由编译器通过引用计数和长度信息自动维护字串内存区域。事实上,当把一个string类型的变量当成字符指针看的时候,他的内存布局是这 样的:

s:   string   =   'CSDN '; 
则有PChar(s)^   =   'C ',(PChar(s)+1)^= 'S ',……(PChar(s)+4)^=#0。 
且:PInteger(Integer(Pointer(s))-1*sizeof(DWORD))^=length(s) 
和:PInteger(Integer(Pointer(s))-2*sizeof(DWORD))^=refcount(s)

可视化一下就是: 
[RefCount:   DWORD][Length:   DWORD]^[ 'C '][ 'S '][ 'D '][ 'N '][#0] 
(^处即为s所指内存地址)

可 以看到string在s之后的内存布局同PChar完全一致,都是ASCIIZ标准的字串,因此任何string类型的变量都可以通过强制类型转换的语法 欺骗编译器的强类型检查而作为PChar直接使用,如:   PChar(s)。而且由于字串的长度存放在偏移-4处,因此求字串长度的时候速度极快,因为length(s)   =   PInteger(Integer(Pointer(s))-4)^,不用像PChar和array那样从头数到尾直到#0。那引用计数是干哈的呢?首先 要明确一点,Delphi对于string是从堆中自动分配和释放内存,分配好说,但是什么时候释放呢?如果你了解COM的引用计数原理就知道,通过维护 refCount系统就能够确定可以安全释放对象的时机了。因为Delphi对于string类型的字串使用了copy-on-write技术,因此如果 简单的两个string都包含相同的内容,则实际上内存中仅有一份拷贝。如: 
s1   :=   'I   love   Delphi ';   //   line   1 
s2   :=   s1;   //   line   2 
s1   :=   s1   +   '! ';   //   line   3 
在 第一行,Delphi将为s1分配内存并设定好负偏移处的长度信息与引用计数(初始为1);在第二行,事实上没有任何的内存分配操作,s2简单的被赋予 s1的指针信息,同时他们指向的字串的引用计数+1(事实上Delphi程序内部还有一张表来记录这些引用信息和变量实例的关系);在第三行,s1进行了 改变,根据内部的逻辑规则,Delphi将自动分配新的内存并实际拷贝s1+ '! '的内容到新的内存中,然后改变s1的地址和s2指向字串的引用计数就搞定了。这就是所谓的copy-on-write。你说了,这没什么用啊,哪儿这么 多直接的赋值啊?其实像返回字串的函数这类情况都能发挥copy-on-write的好处,经济、快速。

综合一下,在Delphi编程 中应该尽可能的使用string类型简化代码、减少出错并提高程序的运行效率。在调用C或者其他应用PChar的场合可以直接拿 PChar(string)来用,不存在效率问题(因为只是强制转换而已)。字符数组主要用于定宽字串和定义结构时候用,不过只有下标为0且数组成员类型 为char的array才和PChar兼容

delphi string,pchar,char的比较的更多相关文章

  1. Delphi的字符(Char),字符串(String),字符串指针(PChar),字符数组arrayofchar(来自http://delphi.cjcsoft.net/论坛)

    Delphi有三种类型的字符: AnsiChar这是标准的1字节的ANSI字符,程序员都对它比较熟悉. WideChar这是2字节的Unicode字符. Char在目前相当于AnsiChar,但在De ...

  2. PChar,PAnsiChar,String,AnsiString,Char数组,AnsiChar数组转换

    PChar,PAnsiChar,String,AnsiString,Char数组,AnsiChar数组之间的转换关系见下图 通过转换链,可以实现任意两个类型之间的互转.如PChar转PAnsiChar ...

  3. delphi string.split 按照任意字符串分割语句

    delphi string.split 按照任意字符串分割语句 1.就是把一个指定的字符串用指定的分割符号分割成多个子串,放入一个 TStringList 中 function ExtractStri ...

  4. QString, string, int, char* 之间相互转换

    这三种数据类型在实际运用中经常需要互相转换,那么这里小结下它们之间的转换方法: - Qstring & string Qt中封装的类十分强大,其成员函数数量之多比STD有过之而无不及,许多程序 ...

  5. Delphi String 常用字串符处理函数

    Delphi 在面对跨平台开发,程序语言也改进不少,不过有些改进,让原本 Delphi 开发者有些不适应,最显注的就是字串处理函数了,原本 Pascal 语言字串起始由 1 开始,几乎是它的经典了,新 ...

  6. string to char* and char* to string 玩转 String 和 Char*

    char 类型是c语言中常见的一个数据类型,string是c++中的一个,它的定义为 Strings are objects that represent sequences of character ...

  7. string,const char*,char*之间的相互转换

    1. string转const char* string s = "abc"; const char* c_s = s.c_str(); 2. const char*转string ...

  8. string与char之间的互相转换

    string对象是一种很强大的存在哈~~ 1. string转const char* string s = "abc"; const char* c_s = s.c_str(); ...

  9. c++ string 与 char 互转 以及base64

    c++ string 与 char 互转 很简单如下 ] = {'A','B','C','D','E'}; printf("%s\n",bts); //char to string ...

随机推荐

  1. Java串口编程学习1-环境配置(64位Win7)

    最近在做zigbee的课程设计,需要Java实现对串口数据的读写操作. 网上找了很多代码,好像都比较过时了,直接拿来用没法跑通……QAQ……然后自己写个教程留底,如有不当之处还请各位路过的大神赐教. ...

  2. POJ 1015 Jury Compromise (动态规划)

    dp[i][j]代表选了i个人,D(J)-P(J)的值为j的状态下,D(J)+P(J)的最大和. #include <cstdio> #include <cstring> #i ...

  3. UVA 11297 Census(二维线段树)

    Description This year, there have been many problems with population calculations, since in some cit ...

  4. DFS(2)——hdu1241Oil Deposits

    一.题目回顾 题目链接:Oil Deposits 题意:给你一块网格,网格被分为面积相等的地块,这些地块中标记'@'的是油田,标记'*'的不是油田.已知一块油田与它上下左右以及对角线的油田同属一片油区 ...

  5. UnrealEngine4入门(二) 实现一个可用按键控制的球体

    源码摘自官网guide,加上部分自己的理解和注释 接上篇博客 本文实现一个可用WASD控制滚动的球体 先创建一个可见的球体: 在CollidingPawn.cpp的构造函数ACollidingPawn ...

  6. 程序运行bug查看

    1.左击计算机进入管理,点击windows日志,查看程序信息. 可以方便看到报错信息.

  7. POJ 3415 后缀数组+单调栈

    题目大意: 给定A,B两种字符串,问他们当中的长度大于k的公共子串的个数有多少个 这道题目本身理解不难,将两个字符串合并后求出它的后缀数组 然后利用后缀数组求解答案 这里一开始看题解说要用栈的思想,觉 ...

  8. BZOJ4008. [HNOI2015]亚瑟王 期望概率dp

    看到这道题想什么? 一个好转移的状态由于T最多444所以把每个点控制在O(400000)以内,所以对于n和r最多乘一次因此猜f[n][r],f[r][n],首先一轮一轮的搞不好转移,那么先想一想f[n ...

  9. 解决IE下页面空白或者报错:[vuex] vuex requires a Promise polyfill in this browser

    [vuex] vuex requires a Promise polyfill in this browser 上述错误的原因是不支持 Promise 方法,导致页面出现空白无法加载. 解决方法如下: ...

  10. CentOS 6通过yum升级Git

    By francis_hao    Mar 9,2017   在一个新机器上推送代码到github上时出现了下面的问题 error: The requested URL returned error: ...