指针的几种形式(常量指针和指针常量,指针数组和数组指针,指针函数和函数指针,数组和指针)

int const* a;

a是指向整形常量的指针,a指向的元素为常量,但a本身可以修改。等效于const int* a;

 

int* const a;

a是指针常量,a本身不能修改,但是a的指向的元素可以修改。

 

const int* const a;

a是指向常量的且本身不能修改的指针。

 

int *a[10];

a是指针数组,a是含有10个元素的数组,数组中的元素为指向整形元素的指针。Sizeof(a)=10*4=40。需要说明的是,这个4不是int的大小,而是因为a保存了10个指针,一个指针的大小为4.即使double* a[10],char* a[10],sizeof(a)也等于40

 

int (*a)[10]

a是数组指针,a是一个指针,这个指针指向一个包含10个整形元素的数组。

Sizeof(a)=4,因为a只是一个指针。

 

int** a;

a是指向指针的指针

 

int (*a)(int);

a是一个函数指针,指向含有一个int型的参数且返回值为int的函数。

 

int* a(int);

a是一个函数,函数的参数为int型,返回值为int*

 

int (*a[10])(int)

a是一个函数指针数组,包含10个元素,数组中的元素为函数指针,该函数指针指向参数为int且返回值为int的函数。

 

int(*a(int))(int,int)

a是一个函数,其返回值为int (*)(int,int),也就是返回值为函数指针。a接受为一个int的参数。

 

 

最后谈一下指针在数组中的运用

1、  一维数组和指针

int a[]={1,2,3,4,5};

int* ip=a+1;     //因为a的类型是int*,+1就要往后移动4个字节,即ip指向元素2的地址

int* ip=(int*)(&a+1); //因为a的类型是int(*)[5],+1就要往后移动20的字节,也就数组最后一个元素后面一个。最后强制转换成int*

 

数组名会转换为指针,指向数组的首地址。所以a和&a的值是一样的,都是数组的首地址。

但是a和&a是不一样的,a的类型是int*,而&a的类型是int(*)[5]

 

void testFun(void)

{

       inta[5]={1,2,3,4,5};

       int*ptr=(int*)(&a+1);

       printf("*(a+2)=%d,*(ptr-2)=%d\n",*(a+2),*(ptr-2));

}

*(a+2)=3,*(ptr-2)=4

强调一点,数组的首地址是常量,不能对其进行赋值操作。

 

指针运算在高维数组中的应用

以二维数组为例,inta[4][5]

该声明意味着a是一个包含4个元素的数组,其中每个元素都是一个由5个整数组成的数组。

a数组的第0个元素是a[0],然后依次为a[1],a[2],a[3],a表示指向数组首元素a[0]的指针,即a的类型int(*)[5].

而a[0]本身就是一个由5个int组成的数组。a[0]数组的第0个元素是a[0][0],该元素是一个int,a[0]表示指向数组a[0]首元素a[0][0]的指针。

而&a表示数组的首地址,其类型为int(*)[4][5],所以&a+1,后移4行5列20个元素。

则有:

a:类型为int(*)[5],即a为指向数组a第0个元素a[0]的指针,且a为常量,不可进行赋值运算。a+i的类型同样int(*)[5],指向a[i];

*a或者a[0]:类型为int*,*a指向数组a[0]首元素a[0][0]的指针。

*(a+1)或a[1]:类型也是int*,因为a的类型为int(*)[5],即a指向一个有5个元素的一维数组,故a+1将

跳过5个元素。则(a+1)为指向数组a的第1个元素a[1]的指针,即*(a+1)或a[1]为指向数组a[1]首元素a[1][0]的指针

*(*(a+1)+2)类型为int,因为*(a+1)类型为int*,故(*(a+1)+2)将跳过两个元素。则(*(a+1)+2)为指向数组a[1]第2个元素a[1][2]的指针,即*(*(a+1)+2)为数组a[1]第2个元素a[1][2]。

总结一下:

&a的类型为int(*)[4][5]

a+i的类型为int(*)[5]

*(a+i)的类型为int*

*(*(a+i)+j)的类型为int

*(a+i)=a[i]类型为int*

*(*(a+i)+j)=*(a[i]+j)=a[i][j]

 

 

void指针

void指针可以指向任何类型的数据,亦即可用任何数据类型的指针对void指针赋值。

int* pInt;

void* pVoid;

pVoid=pInt;     //不过不能pInt=pVoid;如果要将pVoid赋给其他类型指针,则需要强制类型转换如:pInt=(int*)pVoid;

 

由于void指针可以指向任何类型的数据,亦即可用任何数据类型的指针对void指针赋值,因此还可以用void指针作为函数的形参,这样函数就可以接受任意数据类型的指针作为参数。

void* memcpy(void* dest,const void*src,size_t len);

void* memset(void* buffer,int c,size_tnum);


#include <iostream>

using namespace  std;

int main()

{

       double*(*a)[3][6];

       cout<<sizeof(a)<<endl;                        //4

       cout<<sizeof(*a)<<endl;                       //72

       cout<<sizeof(**a)<<endl;                      //24

       cout<<sizeof(***a)<<endl;                     //4

       cout<<sizeof(****a)<<endl;                    //8

}

a是指针,指向一个数组,这个数组是一个3行6列的二维数组,且这个数组的元素类型是double*,故a的类型为*(*)[3][6]。

cout<<sizeof(a)<<endl;  输出4,因为a为一个指针。

cout<<sizeof(*a)<<endl;  输出72;因为*a为一个3行6列的数组,且元素类型为double*,故占用内存3*6*4=72。

cout<<sizeof(**a)<<endl;  输出24;*a为一个3行6列的数组,所以**a为此数组首元素*a[0],*a[0]也是一维数组,且为一维数组,长度为6,元素类型为double*,故**a占用内存大小为6*4=24

cout<<sizeof(***a)<<endl;  输出4;因为**a是一个一维数组,长度为6,元素类型为double*,故***a是一维数组的一个元素,类型为double*,故***a占用内存大小为4

cout<<sizeof(****a)<<endl;   输出8;因为***a类型为double*,故****a类型为double,故占用内存大小为8.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值