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.