指针的定义:(在计算机内存中,每个字节单元都有一个编号,称为地址)在C语言中,内存单元的地址称为指针,专门用来存放地址的变量,称为指针变量
在不影响理解的情况中,有时对地址、指针和变量不区分,统称为指针
一、指针变量的说明
一般形式如下:
<存储类型> <数据类型> * <指针变量名> ;
例如:char * pointerName;
1)指针的存储类型是指针变量本身的存储类型。
2)指针说明时指定的数据类型不是指针变量本身的数据类型,而是指针目标的数据类型。简称为指针的数据类型。
3)指针在说明的同时,也可以被赋予初值,称为指针初始化
一般形式如下:
<存储类型> <数据类型> * <指针变量名> = <地址量>;
例如:int a,*pa = &a;
在上面语句中, 把变量a的地址作为初值赋予了刚刚说明的int型指针pa。
4)指针指向的内存区域中的数据称为指针的目标
如果它指向的区域是程序中的一个变量的内存空间,则这个变量称为指针的目标变量。简称为指针的目标
#include <stdio.h>
int main(int argc, const char *argv[])
{
double a = 10;
double * p ;
p = &a; // 指针p取a的地址
printf("%d \n", *p);// *p取a的目标值,即a的变量10
return 0;
}
5)引入指针要注意程序的px、*px和&px三种表示方法的不同意义。设px为一个指针,则:
px —— 指针变量,它的内容是地址量
*px —— 指针所指向的对象,它的内容是数据
&px —— 指针变量占用的存储区域的地址,是个常量
6)指针的赋值运算指的是通过赋值运算符指针变量送一个地址值
向一个指针变量赋值时,送的值必须时地址常量或指针变量,不能是普通的整数(除了赋零以外)指针赋值运算常见的有一下集中形式:
a)把一个普通变量的地址赋值给一个具有相同数据类型的指针
double x = 20,*px;
px = &x;
b)把一个已有地址值得指针变量赋给具有相同数据类型的另一个指针变量,例如:
float a, *px, *py;
px = &a;//px 取 a的地址
py = px;// py 取 px的地址
c) 把一个数组的地址赋给具有相同类型的指针,例如:
int a[10], *pa;
pa = a; //等价pa = &a[0]即数组首地址
二、指针运算
指针运算是以指针变量所存放的地址量作为运算量而进行的运算
指针运算的实质就是地址的计算
指针运算的种类是有限的,它只能进行赋值运算、算数运算和关系运算
1)指针的算术运算见下表:
指针加减一个n的运算:px + n px - n
注意:
a)不同类型的两个数据实行加减整除运算是无意义的
b)px + n/ -n 表示实际位置的地址量是:
(px) + sizeof(px的类型) * n
(px) + sizeof(px的类型) * n
2)两指针相减运算
a)pa - pb 运算的结果是两个指针指向的地址位置之间相隔数据个数因此,两指针相减不是两指针持有的地址相减的结果。
b)两指针相减的结果值不是地址量,而是一个整数值,表示两指针之间相隔数据的个数。
指针加一减一运算
3)指针的关系运算符
指针关系运算:
a)两指针之间的关系运算表示它们指向的地址位置之间的关系。指向地址大的指针向地址小的指针。
b)指针与一般整数变量之间的关系运算没有意义,但可以和零进行等于和不等于的关系运算, 判断指针是否为空。
int main ()
{
int a[] = {5,8,2,4,9,3};
int y, *p = &a[1];
y = (*--p)++;//括号里先--p从a[1]到a[0]位置,在*号取目标a[0]的值5即(*--p)的值为5所以y等于5
//(*--p)=5,在++,5++就等于6,即a[0]的值就等于6
printf("%d ",y);
printf("%d",a[0]);
}
//输出:5,6
三、指针数组
在c语言中,数组的指针是指数组在内存中的起始地址,数组元素的地址是指数组元素在内存中的起始地址。
1)一维数组的数组名为一维的指针(即起始地址)
int a[8];// 因此,a为a数组的起始地址
2)设指针变量px的地址值等于数组指针x(即指针变量px指向数组的首元素),则:
x[i]、*(px + i)、*(x + i)和px[i]具有完全相同的功能:访问数组第 i + 1个数组元素
3)注意:
指针变量和数组在访问数组中元素时 ,一定条件下其使用方法具有相同形式,因为指针变量和数组名都是地址量,但指针变量和数组的指针(数组名)在本质上不同,指针变量是地址变量而数组的指针是地址常量
//将数组元素反序打印
#include <stdio.h>
int main(int argc, const char *argv[])
{
int a[] = {3, 7, 4, 12, 9};
int *p ,*q ,tmp ;
int n = sizeof(a) / sizeof (int);//计算数组长度
p = a;//指向首地址
q = &a[n-1];//指向尾地址
while(p < q){
tmp =* p;
*p =* q;
*q = tmp;//交换位置
p++;//前进
q--;//后退
}
for(int i = 0;i < n; i++){
printf("%d ",a[i]);
}
puts("");
return 0;
}
4)行指针(数组指针)
存储行地址的指针变量,叫做行指针变量。形式如下:
<存储类型> <数据类型> (*<指针变量名>)[表达式];
例:int a[2][3] ; int (*p)[3];
方括号中的常量表达式表示指针加1;移动几个数据。当用行指针操作二维数组时,一般写成1行的元素个数,(如上表达式 (*p)[3] 表示此行有三个元素)即列数。
//遍历二维数组
#include <stdio.h>
int main(int argc, const char *argv[])
{
int a[3][2] ={{3, 7},{ 4, 12},{ 9, 8}};
int (*p)[2] ;
p = a;
for(int i = 0;i < 3;i++){
for(int j= 0;j < 2;j++){
printf("%5d %5d %5d %5d\n",a[i][j],p[i][j],*(*(a+i)+j),*(*(p+i)+j));
}//四种不同的遍历方式
}
return 0;
}