标签:c语言
了解指针之前先了解一些知识:
变量有关概念: 存储内容<==>数据值
空间大小<==>数据类型
空间位置<==>地址
生存周期<==>存储类别
变量的地址:系统为变量分配的内存单元的地址(无符号整型数)
变量的访问:直接访问:按变量地址存取变量值的方式
间接访问:通过访问一个指向你所要访问的变量的地址的变量,再去访问
指针
定义:为了方便访问内存中的内容,给每一个内存单元(字节)一个编号,这个编号,称为地址,也就是指针(指针就是内存地址,一个变量所在的内存地址就是该变量的指针)
指针是一种数据类型
指针常量:通过&来表示: &变量名
指针变量:存储地址的变量
为了表示指针变量与它所指向的变量之间的联系,用“*”符号表示“指向”
指针变量定义:基类型 * 指针变量名
指针变量的赋值(初始化):
0.直接赋值NULL或者0
1.相同类型变量的地址
2.相同类型的指针变量
指针运算符:&:取地址运算符,取变量内存地址,即取指针。
*:解析引用符(指针运算符),取内容,取内存地址对应的变量,即取指针所指的变量。
通过变量去访问数据:直接访问
通过地址去访问数据:间接访问
int a=3;//定义变量a
int *p; //定义指针变量p
p=&a; //给指针变量赋值,把a的地址赋值给p
int *p1=&a;// 或者直接在定义时赋值
任意类型的指针内存大小都是为4个字节
cout<<sizeof(int*)<<endl;
void 型指针可以指向任意类型
指针+(-)整数:指针的偏移
p+1:1表示的含义:1个单位=sizeof(指针指向的类型)
p++等价于p=p+1,p--等价于p=p-1
举例说明:
intmain(intargc, char **argv)
{ int a[5] = {1, 2, 3, 4, 5};
int *p1 = (int *)(a+1);
int *p2 = (int *)(&a+1);
cout<<*(p1-1)<<endl;
cout<<*(p2-1)<<endl;
return 0;
}
*(a+1)就是a[1],*(ptr-1)就是a[4],执行结果是1,5
&a+1不是首地址+1,系统会认为加一个a数组的偏移,是偏移了一个数组的大小(本例是5个int)
int *ptr=(int *)(&a+1);
则ptr实际是&(a[5]),也就是a+5
原因如下:
&a是数组指针,其类型为 int (*)[5];
而指针加1要根据指针类型加上一定的值,
不同类型的指针+1之后增加的大小不同
a是长度为5的int数组指针,所以要加 5*sizeof(int)
所以ptr实际是a[5]
但是prt与(&a+1)类型是不一样的(这点很重要)
所以prt-1只会减去sizeof(int*)
a,&a的地址是一样的,但意思不一样,a是数组首地址,也就是a[0]的地址,&a是对象(数组)首地址,a+1是数组下一元素的地址,即a[1],&a+1是下一个对象的地址,即a[5].
C规定:数组名代表数组中的首地址
C规定:如果指针变量p已指向数组的一个元素,则p+1指向同一数组中的下一个元素,并不是将p的值(地址)简单加1。(移动一个数组元素所占的字节数)
指针与一维数组:(指针变量的赋值) 3.相同类型的一维数组名给指针变量赋值
int a[5]={2,5,3,6,8};//定义数组变量a
int *p; //定义指针变量p
p=&a; //给指针变量赋值,把a的首地址赋值给p
或者在定义时赋值:
int *p=&a[0];
for(int i=0;i<5;i++)
cout<<p[i]<<endl;//指针与下标的形式操作数组
指针访问数组元素:
数组元素都是连续存放的,数组变量本身保存了第一个数组元素的地址,系统可以快速定位各元素所在内存,从而快速访问数组元素。
元素地址=首地址 + 数组元素类型占用字节数 *索引
指针变量加减n时,代表将该指针的地址加减n*变量字节大小。
如果arr是数组,arr+1代表索引为1的元素地址,arr存放索引为0的元素地址, arr+1与 &arr[1]等价
如果arr是数组,*(arr+1)取索引为1的元素值,即*(&arr[1])。*(arr +1)与arr[1]等价
当两个指针变量指向同一个数组时:
两个指针变量可以比较,指向前面元素的指针小于指向后面元素的指针;
两个指针变量可以相减,返回两个指针所指数组之间元素的个数。
专门的类型 数组指针:指针指向多维数组(数组名赋值)
intn[3][4]={
{1, 3, 5, 7},
{2, 4, 6, 8},
{9,10,11,12}
};
int*p= &n[0][0];
for(inti=0;i<12;i++)
{
cout<<*(p+i)<<endl; //三者含义相同,均表示输出第几个元素
cout<<*(n[0]+i)<<endl;
cout<<*(&n[0][0]+i)<<endl;
}
cout<<sizeof(p)<<endl;
cout<<sizeof(&n[0][0])<<endl;
cout<<sizeof(n[0])<<endl;//求数组的大小(二维数组第一行)
下面四个值一样,但是含义不一样.
cout<<*n<<endl; //n[0]
cout<<*&n[0]<<endl; //n[0]
cout<<*n[0]<<endl; //n[0][0]
cout<<*&n[0][0]<<endl; //n[0][0]
定义一个数组指针pn:指向列数为4的二维数组
int (*pn)[4]=n;
定义一个指针数组:数组中每一个元素都是int指针
int *ppn [3]={n[0],n[1],n[2]};
定义一个二级指针:指针变量中保存另一个指针变量的地址
int **pp=ppn; //ppn数组名等于&ppn{0]
//cout<<*(*(pn+2)-2)<<endl;//6
//cout<<*(*pn+2)-2<<endl;//3
//cout<<*(pn[2]+1)<<endl;//10
//cout<<*(*(ppn+1)-2)<<endl;//5
//cout<<*(*(pp+2)+2)<<endl;//11
//cout<<*(pp+1)[0]<<endl;//2 n[1][0]
//cout<<(*(pp+1))[1]<<endl;//4//n[1][1]
指针变量也是变量,也有自己的存储地址,如果再次定义变量来保存指针变量的存储地址,这个地址就是指向指针变量的指针。
语法:类型** 变量名;
voidzhizhentest4_2(){
inta = 5;
int*p = &a;
int**pt = &p;
printf("%p\n",p);
printf("%p\n",pt);
printf("%d\n",**pt);
}
输出:
0012FEB4
0012FEB0
5
指针变量p保存的是a的地址0012FEB4
指针变量pt保存的是p的地址0012FEB0,而p本身保存的是指针,所以pt保存的是指向指针变量p的指针(内存地址)
*pt表示获取pt所指向的变量p,而p本身也只指针变量,保存的是a的地址,所以还需要再加一个*来取p所指的
(指针变量的赋值) 4.字符串可以给指针变量赋值
定义一个数组c用字符串初始化:把字符串中的每一个字符赋值给每一个元素
char c[10]="abcd";
c[10]="abcd";//错误,c[10]:数组的第11个元素,数组越界。数组元素(char)不能用字符串赋值
c="abcd";//错误,c数组名,首地址指针.常量
char c1[10]="abcd";
定义一个指针p用字符串初始化:把字符串的首地址赋值给指针
char *p="abcd";//字符串有自己独立的内存
p="abcd";//正确
char *p1="abcd";
cout<<p<<endl;
查看字符串的首地址
cout<<(int *)p<<endl;
cout<<(c==c1)<<endl;//输出0;两个数组的首地址肯定不一样
cout<<(p==p1)<<endl;//输出1;相同字符串同一段内存
函数的入口就是该函数的入口地址
可以通过一个指针指向函数,然后通过该指针变量来调用函数
函数指针定义:
数据类型(*指针变量名)(函数参数表列)
给函数指针变量赋值,只需要给出函数名而不必给出参数
对函数指针,指针与运算符的运算无意义
返还指针值的函数(指针型函数)定义:
类型名 * 函数名(参数表列)
const尽量理解为只读类型,不要理解为常量
const int n=10; //符号常量:必须初始化,不能修改值(就是不能赋值)
n=10; //错误;常量不能赋值
intconst m=20; //const 也可以写在数据类型后面
int *p5=&n;//错误
常量指针:只读类型指针
const int * p;
int const * p1;
p = &n;
int n1=20;
p=&n1;//常量指针可以改变指向(指向变量)
*p=30;//错误,常量指针不能通过指针取修改变量的值
指针常量:指针本身是一个常量:必须初始化
int * const p2=&n1;
*p2=40;//可以通过指针常量修改变量的值
p2=&n; //错误,指针常量不能改变指向
int *const p3=&n;//错误,普通类型的指针变量不能指向常量(const类型的数据)
指向常量的指针常量:只读类型的指针常量:既不能改变值,也不能改变指向
const int *const p4=&n;
本文出自 “毕业---觉醒---行走” 博客,请务必保留此出处http://tjy888.blog.51cto.com/5576345/1714415
标签:c语言
原文地址:http://tjy888.blog.51cto.com/5576345/1714415