指针与数组(1)
2016-04-09 18:34
197 查看
说到C语言,指针绝对是c语言的压轴出场,是c语言的重头戏,也是C语言的精华所在,由于指针的存在,我们可以直接对内存空间操作,拿到某个变量的指针(得到它的地址),那么它那块空间就属于我的了,想干什么就干什么!!!!学习C和C++的同学肯定不会对指针感到陌生,这确实是个让我们又爱又恨的东西。
不曾忘记,因为指针操作引起的内存泄露、段错误而彻夜难眠;
也不曾忘记,因为指针的灵活和强大,让我们自由地游刃在内存之中。
就好像c++里由于虚函数的存在,出来一个虚表,那么只要拿到这个虚表的指针(虚表的地址就是该对象的首地址),那么对于父类和子类的无论私有还是保护的成员函数,我们都可以拿来用,因为我们已经越过了private或者protected的防盗网,直接进入了仓库,所以使得累的封装和安全性受到了威胁!所以指针确实是个很强大的东西,这是我的一点儿小体会,可能不太准确,见者海涵!下面来说说指针与一维数组!!!
指针:指针是一个装地址的变量;
内存地址:每一个字节都有唯一的标识符;
地址云算符:&变量名;
间接运算符:*地址;
注意:
1.不要对未初始化的指针操作;
2.对于堆内存分配的空间,在delete或者是free()后,一定要给指针赋空值;防止野指针的产生;
下面上一段代码示例:
指针就是一个装着某种类型地址的变量;
注意:指针类型的+-,都是+-指针对应的字节数;
int *p=NULL;p++ +4;
double *p=NULL;p++ +8;
数组其实是一种比较特殊的数据类型,它所分配的内存空间是连续的,查找效率比较高,但是删除和插入较链表就显得比较笨拙低效;
上一段代码示例:
这里想着重说一下sizeof(&a)和sizeof(a);a是一维数组的名字
代码的实验大部分都是在VC6.0上实现的,由于个人习惯原因,虽然该编译器比较老,但是可能刚接触的就是它,习惯了吧!!!这样也导致了部分实验的结果可能因为编译器的不同而不同,若有错,欢迎指正,望海涵!
因为这两句话我思考了好久,也看了一些资料:
最后发现也许是VC6.0比较老的缘故,它的sizeof(&a),在VS2005上运行的时候结果是:4.而VC6上的结果是12;然后sizeof(a)都是12,没问题!
我们知道a=&a[0]是int *类型的;
&a是int *
类型的,[b]n代表的是元素的个数;[/b]
因为我在VS2005上运行的结果如下:
=&a;那么p=&a;
sizeof(p)=sizeof(&a)就应该=4;就是一个地址而已,只要是地址,其大小就是4字节(32位)。
BUT
[b]因为VC6中的sizeof(p)=4,sizeof(&a)=12;
[/b]
可是在VS2005中sizeof(&a)=4,但是其类型还是int (*)
,类型的,并不是int *类型的,因为上面的代码也有体现:
*(*(&a+1)-1)=*(*(p+1)-1)=3;
和VS6中的一样,这样看来,VS6中的sizeof(&a)又有它一定的道理,应该是整个数组的空间大小12而不是4!可能是因为数组名确实是个比较特殊的东西吧!
因为数组名本质上是个地址,但不能说是指针,它能给指针赋值,是因为,指针本身的数据结构和数组名(地址)是一样的 都是32位的int,所以这里能通过指针来对数组进行操作; 因为它本身是地址的属性,和指针就可以相互赋值,打通了友好往来的桥梁!!用起来也非常方便!
注意:地址不能++;
例如:
int a=10;
a++;//ok;
++a++;//error,a++是个常数11;不能再++了;
int as[3]={1,2,3};
as++;//error;地址不能++;
as=as+1;//error ,错误同上;
as+1;//OK..这个是可以的;它不是赋值,而是一个地址的移动;这是可以的!没有该变地址as的值,它的值是不允许改变的;
本人愚钝,领悟至此,颇有感慨,与己共勉,陋文浅显,见者海涵。
不曾忘记,因为指针操作引起的内存泄露、段错误而彻夜难眠;
也不曾忘记,因为指针的灵活和强大,让我们自由地游刃在内存之中。
就好像c++里由于虚函数的存在,出来一个虚表,那么只要拿到这个虚表的指针(虚表的地址就是该对象的首地址),那么对于父类和子类的无论私有还是保护的成员函数,我们都可以拿来用,因为我们已经越过了private或者protected的防盗网,直接进入了仓库,所以使得累的封装和安全性受到了威胁!所以指针确实是个很强大的东西,这是我的一点儿小体会,可能不太准确,见者海涵!下面来说说指针与一维数组!!!
指针:指针是一个装地址的变量;
内存地址:每一个字节都有唯一的标识符;
地址云算符:&变量名;
间接运算符:*地址;
注意:
1.不要对未初始化的指针操作;
2.对于堆内存分配的空间,在delete或者是free()后,一定要给指针赋空值;防止野指针的产生;
下面上一段代码示例:
#include <stdio.h> int main() { int a=10; int *p=&a; int **pp=&p; //pp是一个指针,指向的是一个int*(装的是一个指针的地址,该指针指向int);目的是为了能间接对a空间操作; // (&pp)++; //地址不能++;=号左边要求是一个变量; //p++;pp++; //因为p和pp都是变量,所以可以++; int *******************************p1;//这个编译都没有问题,p1是一个指针变量; //其实还可以继续定义: int ***p2=&pp; int ****p3=&p2; printf("%p\n",&a); //a的地址; printf("%p\n",&p); //指针变量p的地址; printf("%p\n",p); //p指向的地址,指向的a的地址;p空间里存的是a的地址; printf("%d\n",*p); //p这个空间,里面装的是10; printf("%p\n",&pp); //二级指针变量的地址; printf("%p\n",pp); //指向的是p的地址; printf("%p\n",*pp); //对p的空间的间接引用;执行读,取,写操作; printf("%d\n",**pp);//对p指向的空间,即a所在空间的间接引用,里面装的是10; return 0; }
指针就是一个装着某种类型地址的变量;
注意:指针类型的+-,都是+-指针对应的字节数;
int *p=NULL;p++ +4;
double *p=NULL;p++ +8;
#include <stdio.h> int main() { int as[4]={1,2,3,4}; double *p=(double *)as; p++; printf("%d\n",*p);//3 return 0; }
数组其实是一种比较特殊的数据类型,它所分配的内存空间是连续的,查找效率比较高,但是删除和插入较链表就显得比较笨拙低效;
上一段代码示例:
#include <stdio.h> int main() { int a[3]={11,22,33}; printf("%p\n",&a); //0012ff3c printf("%p\n",a); //0012ff3c printf("%p\n",&a[0]);//0012ff3c /* a==&a a==&a[0] *a==a[0] *(a+2)==a[3]==*(*(&a+1)-1) 一定要注意类型的大小; */ printf("%d\n",sizeof(&a)); //12---内存地址;类型为4*sizeof(int ) printf("%d\n",sizeof(a)); //12---内存空间名; printf("%d\n",sizeof(a[0]));//4 printf("%d\n",*a); //11 printf("%d\n",*(a+2)); //33 printf("%d\n",*(*(&a+1)-1)); //33 return 0; }
这里想着重说一下sizeof(&a)和sizeof(a);a是一维数组的名字
代码的实验大部分都是在VC6.0上实现的,由于个人习惯原因,虽然该编译器比较老,但是可能刚接触的就是它,习惯了吧!!!这样也导致了部分实验的结果可能因为编译器的不同而不同,若有错,欢迎指正,望海涵!
因为这两句话我思考了好久,也看了一些资料:
最后发现也许是VC6.0比较老的缘故,它的sizeof(&a),在VS2005上运行的时候结果是:4.而VC6上的结果是12;然后sizeof(a)都是12,没问题!
我们知道a=&a[0]是int *类型的;
&a是int *
类型的,[b]n代表的是元素的个数;[/b]
因为我在VS2005上运行的结果如下:
#include <iostream> using namespace std; int main() { int a[3]={1,2,3}; int (*p)[3]=&a; cout<<**p<<endl; //1 cout<<*(*(p+1)-1)<<endl;//3 cout<<*(*p+1)<<endl; //2 cout<<*(*(&a+1)-1)<<endl;//3 cout<<sizeof(&a)<<endl; //4 cout<<sizeof(a)<<endl; //12 system("pause"); return 0; }我看过陈正冲的《C语言深度解剖》,这本书还不错,里面第四章指针与数组讲到(*p)
=&a;那么p=&a;
sizeof(p)=sizeof(&a)就应该=4;就是一个地址而已,只要是地址,其大小就是4字节(32位)。
BUT
[b]因为VC6中的sizeof(p)=4,sizeof(&a)=12;
[/b]
可是在VS2005中sizeof(&a)=4,但是其类型还是int (*)
,类型的,并不是int *类型的,因为上面的代码也有体现:
*(*(&a+1)-1)=*(*(p+1)-1)=3;
和VS6中的一样,这样看来,VS6中的sizeof(&a)又有它一定的道理,应该是整个数组的空间大小12而不是4!可能是因为数组名确实是个比较特殊的东西吧!
因为数组名本质上是个地址,但不能说是指针,它能给指针赋值,是因为,指针本身的数据结构和数组名(地址)是一样的 都是32位的int,所以这里能通过指针来对数组进行操作; 因为它本身是地址的属性,和指针就可以相互赋值,打通了友好往来的桥梁!!用起来也非常方便!
注意:地址不能++;
例如:
int a=10;
a++;//ok;
++a++;//error,a++是个常数11;不能再++了;
int as[3]={1,2,3};
as++;//error;地址不能++;
as=as+1;//error ,错误同上;
as+1;//OK..这个是可以的;它不是赋值,而是一个地址的移动;这是可以的!没有该变地址as的值,它的值是不允许改变的;
本人愚钝,领悟至此,颇有感慨,与己共勉,陋文浅显,见者海涵。
相关文章推荐
- JVM 运行时数据区域
- linux中用户创建与删除以及文件权限查看和修改
- boost解析info文件
- mogodb的一些小事 mongodb+express+node.js增删改查
- codeforces Round #258(div2) D解题报告
- android性能调优工具TraceView的使用
- DOM
- 第七周项目一(2) 求两点间的距离
- VB.net版机房收费系统——结账功能实现(调错与优化)
- 骨骼的一点东西
- 受限波兹曼机导论Introduction to Restricted Boltzmann Machines
- 练习二1005
- Hibernate 关联映射之---- 一对多双向映射
- Java实验2 类的继承性
- caffe的配置过程
- linux常用操作
- 目标特征检测之SIFT特征
- java.lang.ExceptionInInitializerError的原因
- 使用Bitmap遍历Assets目录下图片
- 一些蓝牙(Bluetooth)相关的技术术语表