指针变量:
指针变量的定义形式:
基类型 *指针变量名1,*指针变量名2,…;
指针变量只能指向由定义时基类型规定的类型变量,不能指向其他的变量;
指针变量的赋值:
在定义的同时进行初始化:
int i;
int *p=&i; &取地址计算符,&i表示i的地址。
指针变量的引用:
void main()
{
int a,b,c;
int *p;
a=5;
b=a+3;
p=&a; // 通过&把a的地址赋给了p;
c=*p+3; // 通过指针运算符*把p指向的变量a的值输出,在进行运算;间接访问。
printf("%d,%d\n",a,b);
printf("%d,%d\n",*p,c);
}
例:
输入a,b两个整数,用指针实现先大后小的顺序输出:
void main()
{
int *p1,*p2,*p,a,b;
scanf("%d%d",&a,&b);
p1=&a; // 给指针赋值地址的时候,不加*;* 表示取地址中的内容;
p2=&b;
if(a<b) // 通过交换指针来改变输出的最大最小值,而原数值没变;
{
p=p1;
p1=p2;
p2=p;
}
printf("a=%d,b=%d\n",a,b); // 输出的a,b并没有变化;
printf("max=%d,min=%d\n",*p1,*p2); // 但是指针变化,所以输出变化;
}
以上仅仅改变指针所指的地址,而原地址中的内容并未发生变化!
指针与数组:
一维数组:
数组名是0号元素的地址,是常量,不能赋值
1. 指向数组元素的指针:
指针p既可以指向整型变量(数组名本身即为arr[ 0 ]地址,不需要加&),
也可以指向整形数组的元素( 元素需要加&以取地址 ):
p=&a[0];
p=a;
int *p=&a[0]
int *p=a;
引用一个数组元素的两种方法:
1. 指针法:有*(a+i)和*(p+i)两种形式,都是用间接方式来访问的;
2. 下标法:有a[i]和p[i]两种形式;
例:
用下标法和指针法分别输出数组的全部元素:
void main()
{
int a[10],i,*p;
for(i=0; i<10; i++)
scanf("%d",&a[i]);
for(i=0; i<10; i++) // 指针法之 *(a+i)形式 一定从a的开头输出
printf("%d",*(a+i));
printf("\n");
for(p=a; p<(a+10); p++) // 指针法之 *p形式 输出的是指针p指定后面的数据,不一定从头输出
printf("%d",*p);
printf("\n");
for(i=0; i<10; i++) // 下标法之 a[i]形式 从第i个变量开始,(从零开始)
printf("%d",a[i]);
printf("\n");
for(p=a,i=0; i<10; i++) // 下标法之 p[i]形式 同上
printf("%d",p[i]);
printf("\n");
}
说明:
指针可以实现本身值得改变,数组名则不行。即p++是合法的,但是a++就不可以;
在输出时要注意指针的指向需要归零:
例:
void main()
{
int *p,i,a[5];
p = a;
for(i=0; i<5; i++)
scanf("%d",p++); // 在此时,p指向的是最后一位
// p = a; // 应添加归零: p=a;
for(i=0; i<5; i++,p++) // 未归零直接指针向后移,无法输出正确的值;
printf("a[%d]=%d\n",i,*p);
}
指针的算术运算和关系运算:
1. 指针的算术运算只有在指针指向一串连续变量的存储单元的时候,指针的运算才有意义,
若假定p已经指向a:
1. 计算*p++时,结合方式由右向左,等价于*(i++),即先计算*p,再p++
2. *(++p)和*(p++)不同。
3. (*p)++ 表示p所指的元素值+1,即p=a[0]+1;
4. 基类型相同的两个指针可以相减,但不能相加。
若指针p1,p2都指向a中的元素,但p2在p1后面,则p2-p1就是p1与p2之间的元素个数;
指针的关系运算:
只有基类型相同,且指针指向同一串连续的存储单元的时候,才可以比较(地址值):
int a[5],*p1,*p2,*p3;
p1=&a[1];
p2=&a[4];
则 p1<p2 为真。
if (p3=='\0') printf("p3 points to Null.\n");也是正确的;
指针与二维数组:
二维数组可以看成一维数组,每个一维数组中的元素,又是一个一维数组;
二维数组a[i][j]的地址:
1. &a[i][j] // 最通常的输出
2. a[i]+j // 二维数组中的 a[i]表示的是第i行(从零开始)的首个元素的地址;
3. *(a+i)+j // 同上
4. &a[0][0]+4*i+j // 在第i行前有4*i+j个元素存在(列数为4),即按个数输出
5. a[0]+4*i+j // 同上;
二维数组各类地址及用地址引用元素的各种不同表示形式
a 二维数组名,指向一维数组a[0],即第0行首地址 行地址
a[0],*(a+0),*a 第0行第0列元素地址,即a[0][0]的地址 行地址
a+1,&a[1] 第一行首地址,指向一维数组a[1] 行地址
a[1],*(a+1) 第一行第零列元素地址,即a[1][0]的地址 行地址
a[1]+2,*(a+1)+2,&a[1][2] 第一行第二列元素a[1][2]的地址 元素地址
*(a[1]+2),*(*(a+1)+2),a[1][2] 第一行第二列元素a[1][2]的值 元素地址
例:
输出二维数组有关的值:
void main()
{
int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};
printf("%X,%X,%X,%X,%X\n",a,*a,a[0],&a[0],&a[0][0]);
// 依次输出第零行首地址,a[0][0]的地址,a[0][0]的地址,第0行首地址,a[0][0]的地址;
printf("%d,%d,%d\n",a[1][1],*(a[1]+1),*(*(a+1)+1));
// 输出数组元素a[1][1]的值
}
指向二维数组元素的指针:
与指向普通变量的指针变量相似;
例:
输出二维数组的元素:
void main()
{
int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};
int *p;
for(p=a[0]; p<a[0]+12; p++) // 用指针进行输出;
{
if( (p-a[0])%4==0) printf("\n"); // 每行输出4个元素;
printf("%4d",*p);
}
printf("\n");
}
指向二维数组行的指针变量
int a[3][4];
(*p)[4];
p=a;
p所指向的是包含4个int型,元素的一维数组;
圆括号不能少;
例:
输出二维数组的元素(用二维数组行的指针):
void main()
{
int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};
int (*p)[4]; // 指向含有4个int型元素的一维数组;
int i,j;
p=a;
for(i=0; i<3; i++)
{
for(j=0; j<4; j++)
printf("%3d ",*(*(p+i)+j)); // 标准化二维数组的行输出方式;!!!!!
printf("\n");
}
}