使用成员指针访问运算符数组的方法,总结指针的运算

二次元同好交流新大陆
扫码下载App
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
阅读(2897)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
loftPermalink:'',
id:'fks_',
blogTitle:'指针转化为数组形式',
blogAbstract:'
总结:一个指针变量,用数组方式访问指针所指向的数值时,可以把数组下表的形式转化成指针的形式,转化完成后,如果地址有效,则用数组的方式访问指针所指向的数值是合法的。例如,
&&&&&&&&&& struct S
&&&&&&&&&&{
&&&&&&&&&&&& int a,
&&&&&&&&&&&& int b,
blogTag:'',
blogUrl:'blog/static/',
isPublished:1,
istop:false,
modifyTime:0,
publishTime:4,
permalink:'blog/static/',
commentCount:0,
mainCommentCount:0,
recommendCount:0,
bsrk:-100,
publisherId:0,
recomBlogHome:false,
currentRecomBlog:false,
attachmentsFileIds:[],
groupInfo:{},
friendstatus:'none',
followstatus:'unFollow',
pubSucc:'',
visitorProvince:'',
visitorCity:'',
visitorNewUser:false,
postAddInfo:{},
mset:'000',
remindgoodnightblog:false,
isBlackVisitor:false,
isShowYodaoAd:false,
hostIntro:'',
hmcon:'0',
selfRecomBlogCount:'0',
lofter_single:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}数组指针 指针函数 函数指针 - 很多不懂呀。。 - 博客园
int&& *p[4];&&&&&&&& //指针数组。& 是个有4个元素的数组, 每个元素的是指向整型的指针。(数组的每个元素都是指针)int&& (*p)[4];&&&&&& //数组指针。 它是一个指针,指向有4个整型元素的数组。&&&&&&&&&&&&&&&&(一个指针指向有4个整型元素的数组)int *func(void);&&&& //指针函数。 无参函数, 返回整型指针。           & (函数的返回值为int*)    int (*func)(void);&& //表示函数指针,可以指向无参, 且返回值为整型指针的函数。&&&&& (函数的返回值为int)
右左规则:
因为C语言所有复杂的指针声明,都是由各种声明嵌套构成的。如何解读复杂指针声明呢?右左法则是一个既着名又常用的方法。不过,右左法则其实并不是C标准里面的内容,它是从C标准的声明规定中归纳出来的方法。C标准的声明规则,是用来解决如何创建声明的,而右左法则是用来解决如何辩识一个声明的,两者可以说是相反的。右左法则的英文原文是这样说的:The right-left rule: Start reading the declaration from the innermost parentheses, go right, and then go left. When youencounter parentheses, the direction should be reversed. Once everything in the parentheses has beenparsed, jump out of it. Continue till the whole declaration has been parsed.这段英文的翻译如下:右左法则:首先从最里面的圆括号(未定义的标识符)看起,然后往右看,再往左看。每当遇到圆括号时,就应该掉转阅读方向。一旦解析完圆括号里面所有的东西,就跳出圆括号。重复这个过程直到整个声明
解析完毕。笔者要对这个法则进行一个小小的修正,应该是从未定义的标识符开始阅读,而不是从括号读起,之所以是未定义的标识符,是因为一个声明里面可能有多个标识符,但未定义的标识符只会有一个。现在通过一些例子来讨论右左法则的应用,先从最简单的开始,逐步加深:int (*func)(int *p);首先找到那个未定义的标识符,就是func,它的外面有一对圆括号,而且左边是一个*号,这说明func是一个指针,然后跳出这个圆括号,先看右边,也是一个圆括号,这说明(*func)是一个函数,而func是一个指向这类函数的指针,就是一个函数指针,这类函数具有int*类型的形参,返回值类型是 int。
int (*func)(int *p, int (*f)(int*));func被一对括号包含,且左边有一个*号,说明func是一个指针,跳出括号,右边也有个括号,那么func是一个指向函数的指针,这类函数具有int *和int (*)(int*)这样的形参,返回值为
int类型。再来看一看func的形参int (*f)(int*),类似前面的解释,f也是一个函数指针,指向的函数具有int*类型的形参,返回值为int。
int (*func[5])(int *p);func右边是一个[]运算符,说明func是一个具有5个元素的数组,func的左边有一个*,说明func的元素是指针,要注意这里的*不是修饰 func的,而是修饰func[5]的,原因是[]运算符优先级
比*高,func先跟[]结合,因此*修饰的是func[5]。跳出这个括号,看右边,也是一对圆括号,说明func数组的元素是函数类型的指针,它所指向的函数具有int*类型的形参,返回值类型为
int (*(*func)[5])(int *p);func被一个圆括号包含,左边又有一个*,那么func是一个指针,跳出括号,右边是一个[]运算符号,说明func是一个指向数组的指针,现在往左看,左边有一个*号,说明这个数组的元素是
指针,再跳出括号,右边又有一个括号,说明这个数组的元素是指向函数的指针。总结一下,就是:func是一个指向数组的指针,这个数组的元素是函数指针,这些指针指向具有int*形参,
返回值为int类型的函数。
int (*(*func)(int *p))[5];func是一个函数指针,这类函数具有int*类型的形参,返回值是指向数组的指针,所指向的数组的元素是具有5个int元素的数组。要注意有些复杂指针声明是非法的,例如:
int func(void) [5];func是一个返回值为具有5个int元素的数组的函数。但C语言的函数返回值不能为数组,这是因为如果允许函数返回值为数组,那么接收这个数组的内容的东西,也必须是一个数组,但C语言
的数组名是一个右值,它不能作为左值来接收另一个数组,因此函数返回值不能为数组。
int func[5](void);func是一个具有5个元素的数组,这个数组的元素都是函数。这也是非法的,因为数组的元素除了类型必须一样外,每个元素所占用的内存空间也必须相同,显然函数是无法达到这个要求的,
即使函数的类型一样,但函数所占用的空间通常是不相同的。
实际当中,需要声明一个复杂指针时,如果把整个声明写成上面所示的形式,对程序可读性是一大损害。应该用typedef来对声明逐层
分解,增强可读性,例如对于声明:
int (*(*func)(int *p))[5];可以这样分解:typedef& int (*PARA)[5];typedef PARA (*func)(int *);这样就容易看得多了。答案,同时给出用typedef的分解方法:int (*(*func)[5][6])[7][8];func是一个指向数组的指针,这类数组的元素是一个具有5X6个int元素的二维数组,而这个二维数组的元素又是一个二维数组。typedef int (*PARA)[7][8];typedef PARA (*func)[5][6];int (*(*(*func)(int *))[5])(int *);func是一个函数指针,这类函数的返回值是一个指向数组的指针,所指向数组的元素也是函数指针,指向的函数具有int*形参,返回值为int。typedef int (*PARA1)(int*);typedef PARA1 (*PARA2)[5];typedef PARA2 (*func)(int*);int (*(*func[7][8][9])(int*))[5];func是一个数组,这个数组的元素是函数指针,这类函数具有int*的形参,返回值是指向数组的指针,所指向的数组的元素是具有5个int元素的数组。typedef int (*PARA1)[5];typedef PARA1 (*PARA2)(int*);typedef PARA2 func[7][8][9];
随笔 - 177c语言(3)
指针是一种用于存放另外一个变量地址的变量。ANSIC中用类型void*代替char*作为通用指针的类型。
一个单元可表示一个字符,一对相连的存储单元可表示一个短整数,相邻的四个字节则构成一个长整数
指针由存放一个地址的一组存储单元(通常有两个或四个字节)构成。
取地址运算符&只能用于内存中的对象(变量与数组),它不能对表达式、常量、或者寄存器变量进行操作。
一元运算符*是间接或间接引用运算符,当它应用于指针时,它将访问指针所指向的对象。
一个指针只能指向一个特定类型的对象:每个指针对象也有一确定的数据类型。(例外:指向void类型的指针可转换成指向任何对象类型的指针,但它不能间接引用它自身)
数组下标所能完成的任何运算都可以用指针来实现,指针的运算比数组下标运算的速度快。
”指针加1“的意思是pa+1指向pa所指对象的下一个对象。相应地,pa+i指向pa所指对象之后的第i个元素。
一个类型为数组的变量或表达式的值是该数组第0个元素的地址。故pa=&a[0]
一个用数组和下标实现的表达式可等价地用指针和偏移量来实现。
指针和数组名字之间的区别:指针是变量,数组名字不是变量。
/*strlen :返回字符串S的长度*/
int strlen(char *s)
&&&& for(n=0;*s != '\0'; s++)
&&&&&&&& n++;
引用数组边界之外的对象是非法的。
指针的地址算数运算:如果p是一个指向数组某个元素的指针,那么p++对p进行加一运算使它指向下一个元素,而
p+=i对p进行增量运算使它指向指针p当前所指向的元素之后的第i个元素。
基本的存储分配程序:两个函数(alloc,afree)
第一个函数alloc(n)返回一个指向n个连续字符存储单元的指针,allox函数的调用者可;利用该指针来存储字符序列;
第二个函数afree(p)释放已经分配的存储空间。对afree的调用必须以与调用alloc函数相反的次序进行。
最简单的实现方法:让alloc函数对一个大字符数组allocbuf中的空间进行分配。该数组是alloc和afree
的私有数组。
由于函数alloc和free处理的对象是指针而不是数组下标,其他函数无需知道该数组的名字。所以可以再包含
alloc和free的源文件中将该数组说明为static类型。使得它对外不可见。实际实现时,这个数组最好没有名字,它通过
调用malloc函数或者向操作系统申请一个指向无名存储区的指针来得到。
另外一个需要知道的信息是allocbuf中的空间当前已经使用了多少。使用allocp指向allocbuf数组中下一个空闲单元。
当向alloc申请n个字符的空间时,alloc检查allocbuf数组看有没有足够的剩余空间用于分配。如果有足够的空闲空间,alloc就返回allocp
的当前值(。即自由块的开始位置)。然后将allocp加n使它指向下一个空闲区域。
如果空闲空间不够,则alloc返回0。如果p在allocbuf的边界之内,affree仅将allocp的值设置为p.
#define ALLCOCSIZE 10000
static char allocbuf[ALLOCSIZE];
static char *allocp =
char *alloc(int n)
&&&&&&& if(allocbuf+ALLOCSIZE-allocp &= n){
&&&&&&&&&&&&& allocp +=
&&&&&&&&&&&&& return allocp& -
&&&&&&&& }&& else
&&&&&&&&&&&&& return 0;
void afree(char * p)
&&&&&&& if(p &= allocbuf && p & allocbuf + ALLOCSIZE)
&&&&&&&&&&&&&&&& allocp =
//------------------------------------------------------------------------------------------------------------------------------------
static char * allocp -将allocp定义为字符类型指针,并将它初始化为allocbuf的起始地址,该起始地址是程序开始运行时的
下一个空闲位置。
0值的返回表示一个异常事件。
指针和整数不能相互转换,但0例外:常量0可以赋给指针,指针也可以和常量0进行比较。
程序中经常用符号常量NULL代替常量0,常量0是指针的一个特殊值。
1、某些情况下对指针可以进行比较运算:例如指针p和q指向同一数组的成员,那么它们之间可以进行关系比较运算。
任何指针与0进行相等或不等的比较运算都有意义的。但对指向不同数组成员的指针之间的算数或者比较运算,
其执行行为没有定义。(特例:指针的算数运算中可使用一个数组的第一个元素的地址)
2、指针可以与整数进行相加相减运算。
p - n 表示指针p当前所指对象之后的第n个对象的地址。在计算p+n时,n根据p所指对象的大小按比例缩放,而p所指对象的大小决定于p的
说明。例如:一个整数占四个字节的存储空间,那么int对应的n就按4的倍数来计算。
3、指针的算数运算具有一致性:例、如果处理的是比字符类型占据更多存储空间的浮点类型,并且p是一个指向浮点类型的指针
,那么执行p++后p就指向下一个浮点数的地址。所有的指针运算都会自动考虑它所指对象的大小。
有效的指针运算包括:相同类型指针之间的赋值运算;指针值加或减一个整数值的运算;
指向相同数组元素的指针之间的减或比较运算;将指针赋0或指针与0之间的比较运算。所有其它
形式的指针运算均非法。
字符串常量最常见的用处就是用函数变元:
字符串常量可通过一个指向其第一个元素的指针来访问。
pmassage = &now is the time&;
把一个指向该字符数组的指针赋值给指针变量pmessage,其中并未进行字符串的赋值。只涉及到指针的操作。
C语言中没有提供将一个完整的字符串作为一个整体处理的运算符。
char amessage[] = &&&
char *pmassage = &now is the time&;
amessage是一个足以存放字符串初值和空字符‘\0’的一维数组,可以更改数组中的单个字符,但amessage
是一个不可改变的常量,它总是指向同一存储区。
pmessage是一个指针,其初值指向一个字符串常量,之后它可以被修改指向其他地址,但如果试图修改字符串内容,结果将不确定。
/*strcpy :数组下标版本*/
void strcpy (char *s, char *t)
&&& i = 0;
&&& while(s[i] = t[i] != '\0')
&&&& i++;
/*strcpy:指针方法版本*/
void strcpy(char *s, char *t)
&&&& while((*s = *t) != '\0'){
&&&&&&&&&&& s++;
&&&&&&&&&&& t++;
/*strcpy:指针方法*/
void strcpy(char& *s, char *t)
&while((*s++ = *t++) != '\0')
&&&&&&&&&& ;
/*strcpy 指针方法*/
void strcpy(char *s, char *t)
&&&& while(*s++ = *t++)
&&&&&&&&&&&& ;
/*strcmp*/
int strcmp (char *s, char *t)
&&& for(i = 0; s[i] == t[i]; i++)
&&&&&&& if(s[i] == '\0')
&&&&&&&&&&&&& return 0;
&&&&& return s[i] - t[i];
/strcmp:指针方法*/
int strcmp(char *s, char *t)
&&&&&& for(; *s == *t; s++, t++)
&&&&&&&&&&&& if(*s == '\0')
&&&&&&&&&&&&&&&&&& return 0;
&&&&&&&& return *s - *t;
指针数组对于二维数组的一个重要优点是数组的每一行可以有不同的长度。
命令行变元:在程序开始执行时将命令行变元或参数传递给程序。
调用主函数时它带有两个变元:第一个变元(习惯上称作argc,用于变元计数)
的值为程序执行时命令行中变元的数目,第二个变元(称为argv,用于变元变量)
是一个指向字符串数组的指针。
argv[0]的值为调用相应程序的命令名,因此argc的值至少为1.如果argc的值为1
,那么命令名后面没有命令行变元。
函数本身不是变量,但是可以定义指向函数的指针,这种指针可以被赋值,
存放于数组之中,传递给函数及作为函数返回值等等。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:47831次
排名:千里之外
原创:12篇
转载:46篇
(1)(1)(1)(1)(1)(4)(1)(29)(1)(3)(5)(5)(5)又见“数组名就是指针”
[问题点数:100分]
又见“数组名就是指针”
[问题点数:100分]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
2008年2月 VB大版内专家分月排行榜第一2003年4月 VC/MFC大版内专家分月排行榜第一2002年11月 VC/MFC大版内专家分月排行榜第一
2011年11月 VC/MFC大版内专家分月排行榜第二2008年3月 VB大版内专家分月排行榜第二2008年3月 硬件/嵌入开发大版内专家分月排行榜第二2003年4月 其他开发语言大版内专家分月排行榜第二2003年4月 VB大版内专家分月排行榜第二2003年3月 VB大版内专家分月排行榜第二
2013年 总版技术专家分年内排行榜第三
2012年 总版技术专家分年内排行榜第七
2008年2月 VB大版内专家分月排行榜第一2003年4月 VC/MFC大版内专家分月排行榜第一2002年11月 VC/MFC大版内专家分月排行榜第一
2011年11月 VC/MFC大版内专家分月排行榜第二2008年3月 VB大版内专家分月排行榜第二2008年3月 硬件/嵌入开发大版内专家分月排行榜第二2003年4月 其他开发语言大版内专家分月排行榜第二2003年4月 VB大版内专家分月排行榜第二2003年3月 VB大版内专家分月排行榜第二
2012年1月 硬件/嵌入开发大版内专家分月排行榜第二2011年11月 硬件/嵌入开发大版内专家分月排行榜第二2011年10月 硬件/嵌入开发大版内专家分月排行榜第二2011年9月 硬件/嵌入开发大版内专家分月排行榜第二
2012年3月 硬件/嵌入开发大版内专家分月排行榜第三2012年2月 硬件/嵌入开发大版内专家分月排行榜第三
本帖子已过去太久远了,不再提供回复功能。C++ 数组和指针学习总结
定义及其初始化
1、数组的维数必须用值大于等于1的常量表达式定义(包括:整型字面值常量、枚举常量、用常量表达式初始化的整型const对象),非const变量以及到运行阶段才知道其值的const变量都不能用于定义数组的维数。
3、定义数组时没有显式的初始化,则:
----在函数体外定义的内置数组,元素均初始化为0
----在函数体内定义的内置数组,元素均无初始化
----无论在何处定义,若其元素为类类型,则自动调用其默认的构造函数初始化;若无构造函数,则必须为该数组的元素提供显式的初始化
2、字符数组可以使用字符串字面值进行初始化,但当使用字符串字面值来初始化字符数组时,将在数组后面加入空字符,例如:char A[] = &C++&; & //A的维数是4
3、与vector不同,一个数组不能用另一个数组初始化,也不能将一个数组赋值给另一个数组
注意:数组长度固定,一旦定义,就无法添加新的元素。但是若要添加,则需要自己更改内存remalloc()以及malloc()函数可以实现
数组的操作
下标访问。下标的数据类型:size_t
定义及其初始化
建议:尽量避免使用指针和数组
  指针和数组容易产生不可预料的错误。其中一部分是概念上的问题:指针用于低级操作,容易然生与繁琐细节相关的(book keeping)错误。其他错误则源于使用指针的语法规则,特别是声明指针的语法。
  许多有用的程序都可不使用数组或指针实现,现代C++程序采用vector类型和迭代器取代一般的数组、采用string类型取代C风格字符串。
指针可能的取值
  一个有效的指针必然是以下三种状态之一:保存一个特定对象的地址;指向某个对象后面的另一对象;或者是0值。若指针保存0值,表明它不指向任何对象。未初始化的指针是无效的,直到给该指针赋值后,才可使用它。
int ival = 1024; &
 int *pi = 0;      // pi initialized to address no object &
 int *pi2 = &  // pi2 initialized to address of ival &
 int *pi3; & & & & & &// ok, but dangerous, pi3 is uninitialized &
 pi = pi2;       // pi and pi2 address the same object, e.g. ival &
 pi2 = 0;        // pi2 now addresses no object &
指针初始化和赋值操作的约束
  对指针进行初始化或赋值只能使用以下四种类型的值:
  (1)0值常量表达式。
  (2)类型匹配的对象的地址。
  (3)另一对象之后的下一地址。
  (4)同类型的另一个有效指针。
  把int型变量赋给指针是非法的,尽管此int型变量的值可能为0。
  C++提供了一种特殊的指针类型void*,它可以保存任何类型对象的地址:
&pre name=&code& class=&cpp&& double obj = 3.14; &
  double *pd = & &
  // ok: void* can hold the address value of any data pointer type &
  void *pv = & & & & &// obj can be an object of any type &
  pv = & & & & & & & &// pd can be a pointer to any type&/pre& &
----void*表明该指针与一地址值相关,但不清楚存储在此地址上的对象的类型。
----void*指针只支持几种有限的操作:与另一个指针进行比较;向函数传递void*指针或从函数返回void*指针;给另一个void*指针复制。
&----不允许用void*指针操纵它所指向的对象。
指针操作以及指针有关注意事项
一、解引用操作生成左值
二、关键概念:给指针赋值或通过指针进行赋值
对于初学指针者,给指针赋值和通过指针进行赋值这两种操作的差别确实让人费解。谨记区分的重要方法是:如果对左操作数进行解引用,则修改的是指针所指向的值;如果没有使用解引用操作,则修改的是指针本身的值。
三、指针和引用的比较
第一个区别在于引用总是指向某个对象:定义引用时没有初始化是错误的。第二个重要区别则是复制行为的差异:给引用赋值修改的是该引用所关联的对象的值,而并不是使引用与另一个对象关联。引用一经初始化,就始终指向同一个特定对象(这就是为什么引用必须在定义时初始化的原因)。
四、指向指针的指针
指针本身也是可用指针指向的内存对象。指针占用内存空间存放其值,因此指针的存储地址可存放在指针中。
int ia[] = {0, 2, 4, 6, 8}; &
 int *ip = & & & &// ip points to ia[0] &
 ip = &ia[4]; & & & &// ip points to last element in ia &
 ip = & & & & & &// ok: ip points to ia[0] &
 int *ip2 = ip + 4; &// ok: ip2 points to ia[4], the last element in ia &
指针的算数操作只有在原指针和计算出来的新指针都指向同一个数组的元素,或指向该数组存储空间的下一单元时才是合法的。如果指针指向一对象,我们还可以在指针上加1从而获取指向相邻的下一个对象的指针。
五、C++还支持对这两个指针做减法操作:
ptrdiff_t n = ip2 -  // ok: distance between the pointers &
结果是4,这两个指针所指向的元素间隔为4个对象。两个指针减法操作的结果是标准库类型ptrdiff_t的数据。与size_t类型一样,ptrdiff_t也是一种与机器相关的类型,在cstddef头文件中定义。size_t是unsigned类型,而ptrdiff_t则是signed_t整型。
允许在指针上加减0,使指针保持不变。如果一指针具有0值,则在该指针上加0仍然是合法的,结果得到另一个值为0的指针。也可以对两个空指针做减法操作,得到的结果仍是0。
六、解引用和指针算术操作之间的相互作用
在指针上加一个整型数值,其结果仍然是指针。允许在这个结果上直接进行解引用操作,而不必先把它赋给一个新指针:
int last = *(ia + 4);  // ok: initializes last to 8, the value of ia[4] &
加法操作两边用圆括号括起来是必要的。如果写为:
last = *ia + 4;// ok: last = 4, equivalent to ia[0]+4 &
意味着对ia进行解引用,获得ia所指元素的值ia[0],然后加4。
七、计算数组的超出末端指针
&span style=&font-size:14px&& const size_t arr_size = 5; &
  int arr[arr_size] = {1, 2, 3, 4, 5}; &
  int *p = & & & &    // ok: p points to arr[0] &
  int *p2 = p + arr_ & &// ok: p2 points one past the end of arr &
& & & & & & & & & & & &     // use caution -- do not dereference!&/span& &
C++允许计算数组或对象的超出末端的地址,但不允许对此地址进行解引用操作。而计算数组超出末端位置之后或数组首地址之前的地址都是不合法的。
可使用此超出末端指针的当做一个哨兵,如同在vector中使用的end变量一般,用于输出和遍历数组,这是一个好习惯
八、指针和const限定符
指向const对象的指针
const double *    // cptr may point to a double that is const &
const限定了cptr指针所指向的对象类型,而并非cptr本身。也就是说,cptr本身并不是const。
允许通过给cptr赋值,使其指向一个const对象,但不能通过cptr修改其所指向的对象的值。
不能使用void*指针保存const对象的地址,而必须使用const void*类型的指针保存const对象的地址:
const int universe = 42; &
  const void *cpv = & & &// ok: cpv is const &
  void *pv = & & &    // error: universe is const &
不能使用指向const对象的指针修改基础对象,然而如果该指针指向的是一个非const对象,可用其他方法修改其所指的对象。
九、const指针
C++语言还提供了const指针&&本身的值不能修改:
int errNumb = 0; &
 int *const curErr = &errN    // curErr is a constant pointer &
 curErr = curE            // error: curErr is a constant pointer &
指向const对象的const指针,既不能修改所指对象的值,也不允许修改指针的指向。
假设给出以下语句:
typedef string * &
请问cstr变量是什么类型:
&span style=&font-size:12px&& const string * & &// wrong interpretation of const pstring cstr &
 &/span&&span style=&font-size:14 color:#ff0000&& string * & & & &// equivalent to const pstring cstr,等价于这句话&/span& &
C风格字符串
C风格字符串的标准库函数(要使用这些标准库函数,必须包含相应的C头文件:cstring)
strlen(s)       strcmp(s1, s2)      strcat(s1, s2)
strcpy(s1, s2)    strncat(s1, s2, n)    strncpy(s1, s2, n)
注意:这些标准库函数不会检查其字符串参数
永远不要忘记字符串结束符null,调用者必须确保目标字符串具有足够的大小
如果必须使用C风格字符串,则使用标准库函数strncat和strncpy比strcat和strcpy函数更安全
char largeStr[16 + 18 + 2]; & &// to hold cp1 a space and cp2 &
strncpy(largeStr, cp1, 17); & &// size to copy includes the null &
strncat(largeStr, & &, 2);   // pedantic, but a good habit &
strncat(largeStr, cp2, 19); & &// adds at most 18 characters, plus a null &
&对大部分的应用而言,使用标准库类型string,除了增强安全性外,效率也提高了,因此应该尽量避免使用C风格字符串。
创建动态数组
动态数组的定义
int *pia = new int[10];  // array of 10 uninitialized ints &
new表达式返回指向新分配数组的第一个元素的指针
初始化动态分配的数组
可使用跟在数组长度后面的一对空圆括号,对数组元素做值初始化:
int *pia2 = new int[10]();  // array of 10 uninitialized ints &
对于动态分配的数组,其元素只能初始化为元素类型的默认值,而不能像数组变量一样,用初始化列表为数组元素提供各不相同的初值。
const对象的态数组
// error: uninitialized const array &
 const int *pci_bad = new const int[100]; &
 // ok: value-initialized const array &
 const string *pci_ok = new const int[100](); &
允许动态分配空数组
char arr[0]; & & & &      // error: cannot define zero-length array &
char *cp = new char[0];    // ok: but cp can't be dereferenced &
用new动态创建长度为0的数组时,new返回有效的非零指针。该指针与new返回的其他指针不同,不能进行解引用操作,因为它毕竟没有指向任何元素。而允许的操作包括:比较运算,因此该指针能在循环中使用;在该指针上加(减)0;或者减去本身,得0值。
动态空间的释放
动态分配的内存最后必须进行释放,否则,内存最终将会逐渐耗尽。
使用数组初始化vector对象
&strong& &/strong& const size_t arr_size = 6; &
  int int_arr[arr_size] = {0, 1, 2, 3, 4, 5}; &
  // ivec has 6 elements: each a copy of the corresponding element in int_arr &
  vector&int& iec(int_arr, int_arr + arr_size); &
严格地说,C++中没有多维数组,通常所指的多维数组其实就是数组的数组。
&pre name=&code& class=&cpp&&#include &stdio.h&  &&
main()  &&
 static  int  a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}}; /* 定义一个3行4列的二维数组 */ &&
 int  *p;  &&
 printf (&%d %d/n&,a,*a);  &&
 printf (&%d %d/n&,a[0],*(a+0));  &&
 printf (&%d %d/n&,&a[0],&a[0][0]);  &&
 printf (&%d %d/n&,a[0][0],*(*(a+0)+0));  &&
 for  (p=a[0];p&a[0]+12;p++) /* 把a[0]的地址赋予指针变量p,条件判断p&a[0]+12表示的是小于最后一个元素的地址; */ &&
  if ((p-a[0])%4==0) /* 利用整数指针变量p减去当前地址判断出是不是已经显示出了四个值,换行回车 */ &&
  {  &&
   printf (&/n&);  &&
  }  &&
  printf (&%4d&,*p); /* 打印出元素的值 */ &&
 printf (&/n&);  &&
第 5行中的a和*a打印出来的值,就会让人弄不明白我们知道数组传递的地址那么a表示这个数组的其实地址为什么*a却不是实际值呢?原因是在多维数组中 a+0表示的是第0行的首地址,a+1表示是第一行的首地址,那么*a其实就是*(a+0),那么第一个元素其实是a[0][0]&
而*(a+0) 仅仅是把一个3行4列的二维数组拆为了三个一维数组,*(a+0)显然表示的不是物理位置也就不可能得到第一个元素的值了,它仅仅是一个内存地址也就是第 0行的启始地址,再看8行中的*(*(a+0)+0),它表示的则是第0行第0列个元素的值也就是a[0][0],再次强调*(a+0)表示的是数组第一行的首地址,也就是第二行的*(a+1),而元素值要得到显然就是*(*(a+0)+0)了如果是第0行第1个也就是*(*(a+0)+1)。&
*/ &/pre& &
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'

我要回帖

更多关于 用指针访问数组元素 的文章

 

随机推荐