一、指针的基本用法
1、在C语言中使用指针可以使得:
- 程序更加的高效、紧凑、简洁。
- 有效的表达复杂的数据结构。
- 动态分配内存。
- 得到多于一个的函数返回值。
2、基本知识:
- 地址 以及 变量
在计算机中,每一个字节单位,都会有一个编号,这个编号称之为地址。---- 内存以 字节为单位 分配内存。
1Byte(字节) = 8 Bit(位)
- 指针定义:在C语言中,内存单位的地址称为指针;专门用来存放指针的变量,称之为指针变量。
在不影响理解的情况下,一般把地址、指针变量、指针不区分 通称为指针。
- 形式:<存储类型> <数据类型> * <指针变量名> 例如 : auto int *pointer;
#include <stdio.h>
int main(void)
{
int* p;
int a = 1 ;
p = &a;
printf("%d \r\n",*p);
*p = 23;
printf("%p ",p);
printf("%d \r\n",*p);
return 0;
}
以上程序打印出来的结果 :1 0xbffebdf8 23
例子 : int* p =NULL; p 只存放指针, *p 指向存放在 p 地址中的 的地址位置 -------- p也是一个变量,有自己的地址。
- 指针指向的内存区域中的数据称为指针的目标。
如果他指向的区域是程序中的一个变量的内存空间,则这个变量称为 指针的目标变量,简称为指针的目标。
- 例如 px 是一个指针变量 ------- px : 指针变量,他存放的是一个地址量 *px : 指针所指向的对象,他的内容是数据 &px : 指针变量占用的内存区域的地址,是一个常量。
- 指针 的赋值:通过赋值运算符向指针变量送一个 地址值。向一个指针变量赋值时,送的值必须是一个地址常量或,指针变量,不能时一个普通的整数(除了赋零以外)。
1、把一个普通变量 的地址 赋给 相同数据类型的指针变量 ---- double a = 0, *p; p = &a;
1、把一个已知地址值的指针变量赋给另一个具有相同数据类型的指针变量 ---- double a[20], *p; p = a;
3、指针的运算
- 指针运算的实质就是 地址的运算。
- 指针运算是指 以指针变量所存放的地址量作为运算量而进行的运算。
- 指针运算的种类是有限的,它只能进行 赋值预算、算术运算和关系运算。
例如 :int* p ; p = p+2; ------------ p指针向大地址方向递增了两个 int 数据(8个字节) 的位置。
int* p1 ; p1 - p : 相减的结果是两个指针之间相差的(int)数据个数。
指针之间的关系运算一般说的是地址之间的运算,与整数运算没有任何意义,-------- 指针可以跟零进行等于与不等比较,来评断指针是否为空。
例子 :int a [2] = {2,3} ; int* p ; p = &a[1] y = (*--p) -------------- y = 2; (++ 的优先级比 * 高)
4、指针与数组的结合
- 在C语言中,数组的指针是指数组在内存中的起始地址;数组元素的的地址是指数组元素在内存中的起始地址。
- 一维数组的数组名为 一维数组的指针(起始地址)------- 例如 double x[8] 因此,x 为 x的起始地址。
- p ++ 等同于 p = p+1 ------- 该同事会改变P本身的大小。
- int a[4] ; int* p ; p = a; 这时 a[2] 、a+2、*(p+2)、p[2] 是等同的,都表示数组的第二个元素。
题目 :使用指针的方式,将一个数组中的各个元素实现 逆序输出。
#include <stdio.h>
int main(int argc, const char *argv[])
{
int a[5] = {1,2,3,4,5};
int *q,*p;
int t,i,n;
n = sizeof(a)/sizeof(int);
q = a ;
p = &a[n-1];
while(q<p)
{
t= *q;
*q = *p;
*p = t;
q++;
p--;
};
for(i=0;i<n;i++)printf("%d\r\n",a[i]);
return 0;
}
5、指针与二维数组
题目:使用一级指针遍历二维数组。
#include <stdio.h>
int main(int argc, const char *argv[])
{
int a[5][2] = {{1,6},{2,1},{3,3},{4,2},{5,1}};
int *q,*p;
int t,i,n;
n = sizeof(a)/sizeof(int);
q = &a[0][0] ;
for(i=0 ;i<n ; i++)printf("%d \r\n",*(p+i));
return 0;
}
题中 : q 与 a 是不同类型 ------- q 每加1地址加4 ,而a每加1 地址加8。
对于二维数组:带数组名的 不一定 一定是常量,也可能是 指针变量。
- 二维数组 名代表 数组的起始地址,数组名加一,移动一行元素 --- 因此,二维数组名称为 行地址。-- a + 1
- 对于二维数组来说,a[2][3] 可以看作为 2个一维数组组成,每个一维数组中元素有3个 ----- *(a+1)+1表示第二个一维数组(第二行)的第二个元素地址。
- 申请一个行指针 int (*p)[3] ------- 该指针每加1地址将加 12 个字节(一行)。
使用行指针 遍历一个 二维数组:
#include <stdio.h>
int main(int argc, const char *argv[])
{
int a[5][2] = {{2,1},{1,0},{3,6},{4,4},{5,1}};
int (*p)[2];
int i,j;
p = a;
for(i=0;i<5;i++)
for(j=0;j<2;j++)printf("%d %d \r\n",p[i][j],*(*(a+i)+j));
return 0;
}
题中 : p[i][j] 与 *(*(a+i)+j)等价。