C++指针——数组指针/函数指针_C/C++_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > C/C++ > C++指针——数组指针/函数指针

C++指针——数组指针/函数指针

 2015/3/11 21:16:23  香煎马鲛鱼  程序员俱乐部  我要评论(0)
  • 摘要:C++指针——数组指针/函数指针指针对于新手来说是一件非常头疼的事情,特别是二重指针,第一此看的时候一知半解的,在拥有一定的代码量积累之后,终于鼓起勇气再看一遍,其他指针的知识点还好,到了二重指针、函数指针这里就有些难度了,多看了些资料,终于把它攻克了,下面把资料整理出来,以供大家参考:首先鸣谢以下资料,如果作者有哪些讲得不清楚的可以参考一下下面资料,这篇文章就是根据下面资料整理出来的:http://www.cnblogs
  • 标签:函数 c++ 数组 数组指针 函数指针 指针

class="MsoNormal">C++指针——数组指针/函数指针

指针对于新手来说是一件非常头疼的事情,特别是二重指针,第一此看的时候一知半解的,在拥有一定的代码量积累之后,终于鼓起勇气再看一遍,其他指针的知识点还好,到了二重指针、函数指针这里就有些难度了,多看了些资料,终于把它攻克了,下面把资料整理出来,以供大家参考:

首先鸣谢以下资料,如果作者有哪些讲得不清楚的可以参考一下下面资料,这篇文章就是根据下面资料整理出来的:

http://www.cnblogs.com/ggjucheng/archive/2011/12/13/2286391.html

http://bbs.51cto.com/thread-1017222-1-1.html

http://www.cnblogs.com/gmh915/archive/2010/06/11/1756067.html

?

在讲二重指针之前,我觉得有必要了解一下指针的运算:

指针的算术运算

指针可以加上或减去一个整数。指针的这种运算的意义和通常的数值的加减运算的意义是不一样的。例如:??
例二:??

?char a[20];?
?int *ptr=a;?
...?
...?
?ptr++;?


在上例中,指针ptr的类型是int*,它指向的类型是int,它被初始化为指向整形变量a。接下来的第3句中,指针ptr被加了1,编译器是这样处理的:它把指针ptr的值加上了sizeof(int),在32位程序中,是被加上了4。由于地址是用字节做单位的,故ptr所指向的地址由原来的变量a的地址向高地址方向增加了4个字节。
由于char类型的长度是一个字节,所以,原来ptr是指向数组a的第0号单元开始的四个字节,此时指向了数组a中从第4号单元开始的四个字节。

下面我们来看看各种数据类型在32位和64位下的字节数:

常用数据类型对应字节数
??可用如sizeofchar),sizeof(char*)等得出

?32位编译器:

??????char 1个字节
??????char*(即指针变量): 4个字节(32位的寻址空间是2^32, 32bit,也就是4个字节。同理64位编译器)
??????short int : 2个字节
???
???int??4个字节
??????unsigned int : 4个字节
??????float:??4
个字节
??????double:???8
个字节
??????long:???4
个字节
??????long long:??8
个字节
??????unsigned long:??4
个字节
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

??64位编译器:

??????char 1个字节
??????
char*(即指针变量): 8个字节
??????short int : 2个字节
?????
?int??4个字节
??????unsigned int : 4个字节
??????float:??4
个字节
??????double:???8
个字节
??????
long:???8个字节
??????long long:??8个字节
??????
unsigned long:??8个字节

?

指针的指针和数组指针

此图清晰地解释了二重指针以及指针和数组的关系:



?

请看以下代码:

#include<iostream>

usingnamespace std;

?

int main(){

???????? int tab[8] = { 3, 4, 2, 6, 7, 9 };

???????? int tab2[3][4] = { 3, 4, 2, 6, 7, 9 };

???????? cout << *(tab + 3) << endl;//结果为6,指针指向int型,加1移动4个字节,加3移动12个字节

???????? cout << tab[5] << endl;//结果为9,不解释

???????? cout << *(&tab[6]) << endl;//结果为0

???????? cout << *(*(tab2 + 1)) << endl;//*(tab2+1)为指针指向tab2[1][0],因此其结果为7

???????? cout << *(&tab2[0][0] + 1) << endl;//结果为4

???????? cout << *(tab2 + 1) << endl;

???????? cout << &tab2[1][0] << endl;

???????? cout << *(*(tab2 + 1))+1 << endl;

???????? system("pause");

}



?

结果及理由如上图所示。弄懂这结果是怎样来的你就基本掌握了。

例:

int array[10];?
int (*ptr)[10];?
ptr=&array;?
上例中ptr是一个指针,它的类型是int (*)[10],他指向的类型是int [10],我们用整个数组的首地址来初始化它。在语句ptr=&array中,array代表数组本身。

这句话看起来比较难理解,所以我们可以结合另一个例子来理解:

?????? ???????? int *abcde = NULL;

???????? int abcd[9] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };

???????? int abc[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

???????? int **pointer2=&abcde;

???????? int(*pointer)[10] = &abc;

???????? cout << "porinter" << endl;

???????? cout << *(*pointer+1) << endl;

???????? cout << *(*pointer) << endl;

???????? cout << "*porinter&pointer[0]指针的值" << endl;

???????? cout << *pointer << endl;

???????? cout << &pointer[0] << endl;

???????? cout << "porinterabcdpointer指针的值" << endl;

???????? cout << abcd << endl;

???????? cout << pointer2 << endl;

???????? cout << pointer << endl;

???????? cout << "porinterabcdpointer长度" << endl;

???????? cout << sizeof(abcd) << endl;

???????? cout << sizeof(pointer2) << endl;

???????? cout << sizeof(pointer) << endl;

???????? system("pause");

输出结果为:



?

如果让 (*pointer)[10] = & abcd[9]则会报错:(*)[9]类型的值不能指向(*)类型的实体;

所以通过这样的对比,应该可以比较容易地理解什么叫做pointer的指针类型是(*)[10],指向array[10]了吧

?

指针函数和函数指针:

指针函数和函数指针听起来很费解,但理解起来却并不见得比前面那位难:

指针函数是函数:指针函数本质是函数,它的返回值是指针,所以被称作指针函数。

函数指针是指针:函数指针的本质是指针,它指向函数,通过函数指针可以调用函数。

指针函数

函数指针

简介

指针函数本质是函数,它的返回值是指针,所以被称作指针函数

函数指针的本质是指针,它指向函数,通过函数指针可以调用函数

代码

void ?main()

{

???????? int wk, dy;

???????? do

???????? {

?????????????????? printf("Enter week(1 - 5)day(1 - 7)\n");

?????????????????? scanf("%d%d", &wk, &dy);

???????? } while (wk<1 || wk>5 || dy<1 || dy>7);

???????? printf("%d\n", *GetDate(wk, dy));

???????? system("pause");

}

?

int * GetDate(intwk, intdy)

{

???????? staticint calendar[5][7] =

???????? {

?????????????????? { 1, 2, 3, 4, 5, 6, 7 },

?????????????????? { 8, 9, 10, 11, 12, 13, 14 },

?????????????????? { 15, 16, 17, 18, 19, 20, 21 },

?????????????????? { 22, 23, 24, 25, 26, 27, 28 },

?????????????????? { 29, 30, 31, -1 }

???????? };

?

???????? return &calendar[wk - 1][dy - 1];

}

void(*funcp)();

void FileFunc(), EditFunc();

?

void main()

{

???????? funcp = FileFunc;

???????? (*funcp)();

???????? funcp = EditFunc;

???????? (*funcp)();

???????? system("pause");

}

?

void FileFunc()

{

???????? printf("FileFunc\n");

}

?

void EditFunc()

{

???????? printf("EditFunc\n");

}

结果



?

?



?

?

解释

????当一个函数声明其返回值为一个指针时,实际上就是返回一个地址给调用函数,以用于需要指针或地址的表达式中。
????格式:
?????????类型说明符?*?函数名(参数)
????
当然了,由于返回的是一个地址,所以类型说明符一般都是int
????例如:int?*GetDate();
??????????int?*?aaa(int,int);
????
函数返回的是一个地址值,经常使用在返回数组的某一元素地址上。

int (*f) (int x); /*?声明一个函数指针?*/

 f=func; /*?func函数的首地址赋给指针f */

指向函数的指针包含了函数的地址,可以通过它来调用函数。声明格式如下:
????????类型说明符?(*函数名)(参数)
????
其实这里不能称为函数名,应该叫做指针的变量名。这个特殊的指针指向一个返回整型值的函数。指针的声明笔削和它指向函数的声明保持一致。
????????指针名和指针运算符外面的括号改变了默认的运算符优先级。如果没有圆括号,就变成了一个返回整型指针的函数的原型声明。

?

?

?

指针函数问题解决了,但是还是有很多小的问题,我在网上看面试题的时候,遇到了这样一个问题:

参考:(http://www.cnblogs.com/iuices/archive/2011/11/03/2234877.html)

下面几种方式哪种可以实现交换?

void swap1(intp, intq)

{

???????? int temp = NULL;

???????? temp = p;

???????? p = q;

???????? q = temp;

}

?

void swap2(int *p, int *q)

{

???????? int *temp=NULL;

???????? *temp = *p;

???????? *p = *q;

???????? *q = *temp;

}

void swap3(int *p, int *q)

{

???????? int *temp = NULL;

???????? temp = p;

???????? p = q;

???????? q = temp;

}

?

void swap4(int *p, int *q)

{

???????? int temp = NULL;

???????? temp = *p;

???????? *p = *q;

???????? *q = temp;

}

?

void swap5(int &p, int &q)

{

???????? int temp = NULL;

???????? temp = p;

???????? p = q;

???????? q = temp;

}

答案是45,代码在附件里有哦。

?

还有一题是考char str[]char *str的区别的:

这个函数有什么问题?该如何修改?

1

2

3

4

5

char?*strA()

{

????char?str[] = "hello world";

????return?str;

}

?

解析这个str里存在的地址是函数strA栈里“hello world”的首地址。函数调用完成,栈帧恢复调用strA之前的状态,临时空间被重置,堆栈回缩strA栈帧不再属于应该访问的范围。这段程序可以正确输出结果,但是这种访问方法违背了函数的栈帧机制。

????? 但是只要另外一个函数调用的话,你就会发现,这种方式的不合理危险性。

????? 如果想获得正确的函数,改成下面这样就可以:

1

2

3

4

5

char?*strA()

{

????char?*str = "hello world";

????return?str;

}

????? 首先要搞清楚char *str char str[]

1

char?str[] = "hello world";

是分配一个局部数组。局部数组是局部变量,它所对应的是内存中的栈。局部变量的生命周期结束后该变量不存在了。

1

char?*str = "hello world";

?

str[]*str的区别:

其实区别主要在两个地方http://blog.csdn.net/szchtx/article/details/10396149

弄清第一点区别首先要明白常量指针和指针常量的区别:

const char *p; 常量指针,指向一块区域,这块区域不可写,只能读。
char * const p;
指针常量,指向一块区域,这块区域可读可写,但是指针的值初始后就不能改,类似于一般常量。

1

[cpp]?view plaincopyprint?

char?ss[]="C++";??

ss[0]='c';??????????????????//?合法??

char?*p="C++";??

p[0]='c';???????????????????//?合法但不正确??

?

该段代码在VS2010下编译可以通过,但是运行时程序会停止工作,为什么呢?原因在于p[0]='c'这一语句。该语句试图修改p指向的字符串的首个字符,出现了错误

原因在于两种方式对字符数组操作的机制不同。使用char *p="C++"语句后,编译器在内存的文字常量区分配一块内存,保存”C++“这一字符串字面值,然后在栈上分配内存保存pp的内容为"C++"的地址。p[0]='c'试图修改常量”C++“,程序当然就会崩溃了。而char ss[]="C++"语句,定义了一个数组,编译器为其在栈上分配了内存空间,因而可以进行修改操作。

因此,可以总结如下:

1char ss[]定义了一个数组,ss可认为是一个常指针,ss不可改变,但ss指向的内容可以发生改变。

2char *p定义了一个可变指针,p可以指向其它对象。但对于char *p=”abc“这样的情况,p指向的是常量,故内容不能改变。

2

如下代码进一步说明char ss[]char *p的区别:

[cpp]?view plaincopyprint?

char?*strA()??

{??

????char?str[]="Hello";??

????return?str;??

}??


调用该函数,不一定能够得到正确的结果。因为str定义了一个局部数据,是局部变量,存在于函数strA中的栈帧中。当函数调用完成后,栈帧恢复到函数strA调用前的状态,临时空间被重置,为函数分配的栈空间被收回,str所指向的地址也就不存在了。

将上述代码修改:

char?*strA()??

{??

????char?*str="Hello";??

????return?str;??

}??


该函数能够正常运行,因为str指向的字符串字面值被保存在只读的数据段,是全局的,当函数调用完成后,str指向的地址未发生变化。

综上,可以看出使用char []较容易出错,可能出现不确定的结果。C++提供的string类相比之下,要安全的多了。

其实以上解释并不是很易懂,我也不是很懂,其实对C++内存分区不懂得话学习C++是很吃力的,所以附上链接,希望对有需要的朋友有帮助:http://www.cnblogs.com/hanyonglu/archive/2011/04/12/2014212.html

指针的题目有难有易,不过指针这种不是靠做题就能会的,实际灵活运用,才是王道。C++的学习之路远没有结束,哪怕看再多的资料也要躬身学习。如果感觉这些资料对你未来的学习有帮助,就足够了。附上自己整理的代码,希望能对大家有所帮助,再次感谢博客园的大神们~~~

最后知识点梳理,这篇文章介绍了:

?

1、指针运算;2、指针的指针;3、数组指针;4、指针函数和函数指针的区别;5、指针常量和常量指针的区别;6char str[] char *str的区别;

  • 大小: 99.5 KB
  • 大小: 4.1 KB
  • 大小: 27.2 KB
  • 大小: 6.7 KB
  • 大小: 1.1 KB
  • code.rar (1.2 KB)
  • 下载次数: 0
  • 查看图片附件
发表评论
用户名: 匿名