① 使程序简洁、紧凑、高效
② 有效地表达复杂的数据结构
③ 动态分配内存
④ 得到多余一个的函数返回值
在计算机内存中,每一个字节单元都有一个编号,称为地址。指针指向地址,所以指针可以理解为就是地址。(内存以字节为单位 int *p 假如p指向0x00000000 p+1指向0x00000004)
1.3 指针变量的定义在c语言中,内存单元的地址称为指针。
<存储类型> <数据类型> *<指针变量名> char *p;
指针说明指定的数据类型不是指针的数据类型,而是指针目标(*p)的数据类型,比如上面(*p)的类型为字符型char。
1.4 指针变量的赋值指针变量在使用前不仅要定义说明,还要赋予具体的值(地址),不然会出现段错误等情况。未经赋值的指针变量不能随意使用。
如下演示未赋值的情况:
#includeint main(int argc, char const *argv[]) { int *q; scanf("%c",q); //未赋值 没有初始地址,这里执行会出现段错误 printf("%c",*q); return 0; }
如何规避这个问题?
1、对指针进行初始化 2、使用指针前进行非空判断 3、指针使用完成后将指针置空避免出现野指针
C语言提供&地址符来表示变量的地址,我们可以int a = 0; int *p = &a;这样给p一个初始地址。当然也可以这样写,int a = 0; int *p; p = &a;因为只有在定义时需要加*,后面*p全是代表取指针(地址)中存放的内容。
我们对上面的示例进行优化:
#include1.5 指针变量的引用int main(int argc, char const *argv[]) { char i = 0; char *q = &i; if (NULL == q) { printf("q is NULLn"); return -1; } scanf("%c",q); printf("%cn",*q); q = NULL; return 0; }
指针指向的内存区域中的数据称为指针的目标。&是取地址运算符 *是指针运算符,两个运算符互为互逆操作,例如"&a"是取变量a的地址,*b就是取指针变量b所指向内存单元的内容。
如下程序演示:
#includeint main(int argc, char** argv) { int m = 10; int *p = &m; printf("&m:%p,p:%pn",&m,p); //p = &m printf("m:%d,*p:%d,*(&m):%dn",m,*p,*(&m)); // m = *p = *(&m) return 0; }
注意:指针本身也需要地址存放的,&p也会占用一个地址。
指针运算是以指针变量所存放的地址量作为运算量而进行的运算; 指针运算的实质就是地址的计算; 指针运算的种类是有限的,它只能进行赋值运算、算术运算和关系运算;
2.1指针算术运算
px+n演示:
#includeint main(int argc, char** argv) { int m = 10; double n = 20.0; int *p = &m; double *q = &n; printf("m = %d , &m= %p , p = %p , p+2= %pn",m,&m,p,p+2); printf("n = %f , &n= %p , q = %p , q+2= %pn",n,&n,q,q+2); return 0; }
如上所示,p为int型指针,p+2就是p移动42字节 q为float型指针,q+2就是移动82字节。
p-q是两指针只想地址位置直接相隔数据的个数,而非字节个数,如下所示:
#include2.1指针关系运算int main(int argc, char** argv) { int array[5] = {1 , 2, 3, 4, 5}; int *p = &array[0]; int *q = &array[4]; printf("q-p = %ldn",q-p); }
两指针直接的关系运算,表示它们指向地址之间的关系运算,见下表。
注意以下两点:
①具有不同数据类型的指针之间的关系运算没有意义,指向不同数据区域的数据的两指针之间,关系运算也没有意义。
②指针与一般整数变量之间的关系运算没有意义。但可以和零进行等于或不等于的关系运算,判断指针是否为空。
关系运算演示如下,实现字符串的逆序输出:
#include三、指针与数组 3.1 指针与一维数组#include int main(int argc, char const *argv[]) { char s[] = "welcome"; char *p = NULL , *q = NULL , t = 0; printf("%sn", s); p = s; q = s + strlen(s) - 1; while(p < q) { t = *p; *p = *q; *q = t; p++; q--; } printf("%sn", s); return 0; }
1、指针与数组
① 在C语言中,数组的指针是指数组在内存中的起始地址,数组元素的地址是指数组元素在内存中的起始地址
② 一维数组的数组名为一维数组的指针(起始地址),如a[8]的起始地址就是a
③ 设指针变量px的地址值等于数组指针x(即指针变量px指向数组的首元数),则:x[i] 、*(px+i)、*(x+i) 和px[i]具有完全相同的功能:访问数组第i+1个数组元素
指针与数组的异同:①指针变量和数组在访问数组中元素时,一定条件下其使用方法具有相同的形式,因为指针变量和数组名都是地址量。②但指针变量和数组的指针(或叫数组名)在本质上不同,指针变量是地址变量,而数组的指针是地址常量,也就是没有数组名+1这种写法,但是可以指针+1,如下演示情况。
#include#include int main(int argc, char const *argv[]) { int array[10] = {0}; array = array + 1; return 0; }
指针与一维数组关系综合演示:
#include#include int main(int argc, char const *argv[]) { int a[] = {9 , 1 , 34 , 7 , 3 , 10} , i = 0 , n = 0; int *p = a; n = sizeof(a)/sizeof(int); for ( i = 0; i < n; i++) { printf("%d %d %d %dn" , *(a+i),a[i],*(p+i),p[i]); } return 0; }
指针与数组常见等价操作:
① 多维数组就是具有两个或两个以上下标的数组
② 在C语言中,二维数组的元素连续存储,按行优先存,基于这个特点,可以用一级指针访问二维数组
编程实现使用一级指针遍历二维数组:
#include3.2.3 行指针(数组指针)遍历二维数组int main(int argc, char *argv[]) { int a[2][3] = {{1,2,3},{4,5,6}}; int *p = a[0]; //a[0]是第一行首地址 等价于&a[0][0] int i=0,j = 0; for(i = 0;i<2;i++) { for(j=0;j<3;j++) { printf("%d ",*p++); } putchar('n'); } return 0; }
存储行地址的指针变量,叫做行指针变量。形式如下: <存储类型> <数据类型> (*<指针变量名>)[表达式]
例如,int a[2][3]; int (*p)[3]; 方括号中的常量表达式表示指针加1,移动几个数据。 当用行指针操作二维数组时,表达式一般写成1行的元素个数,即列数。二维数组名常被称为行地址。
指针和二维数组关系:
示例:
#include四、综合练习int main(int argc, char *argv[]) { int a[2][4] = {{1,2,3,4},{5,6,7,8}}; int (*p)[4]; p = a; printf("%p %p n",p,p+1); //p+1 行指针移动一行 一行4*4=16bytes 地址间隔16bytes printf("%p %p n",*p,*p+1); //*p = p+0 *p+1 = *(p+0)+1 = &a[0][1] 所以间隔1个数据 地址间隔4字节 printf("%dn",*(*(p+1)+1)); //p[1][1] = a[1][1] = 6 printf("%dn",*(*(a+1)+1)); return 0; }
1、输入char型“123”,转为整数123输出
答:
#include#include int main(int argc, char const *argv[]) { char *s = "123"; int num = 0; while (' ' != *s) { num = num*10 + *s - '0'; s++; } printf("num = %dn", num); return 0; }
2、编写一个函数,将整型数组中的n个数按反序存放
答:
#includeint main(int argc, char const *argv[]) { int a[] = {1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10}; int n = sizeof(a)/sizeof(int); int *p = a; int *q = a + n - 1; int temp = 0; for (int i = 0; i < n/2; i++) { temp = *q; *q = *p; *p = temp; p++; q--; } for (int j = 0; j < n ; j++) { printf("a[%d] = %d ", j , a[j]); } printf("n"); return 0; }
3、编程实现,使用行指针遍历二维数组?
答:
#includeint main(int argc, char *argv[]) { int a[2][4] = {{1,2,3,4},{5,6,7,8}}; int (*p)[4]; p = a; printf("%p %p n",p,p+1); printf("%p %p n",*p,*p+1); for(int i = 0;i<2;i++) { for(int j = 0; j<4;j++) printf("%d ",*(*(p+i)+j)); putchar('n'); } return 0; }
ps:欢迎大佬指正,共同学习进步。



