指针的基本概念
-
地址和指针类型
-
地址与取地址运算
计算机将内存以字节为单位,划分成为一个个存储单元。为了能正确地访问存储单元,必须为 每一个存储单元编号,称为该存储单元的地址。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7M2IbKy5-1637485634411)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1637213216087.png)]
#include<stdio.h> int main() { char ch = '#'; int a = 8; float f = 12.34; printf("变量ch的值:%c\t变量ch的地址:%x \n", ch, &ch); printf("变量a的值:%d\t变量a的地址:%x \n", a, &a); printf("变量f的值:%.2f\t变量f的地址:%x \n", f, &f); return 0; } /* 变量ch的值:# 变量ch的地址:effb63 变量a的值:8 变量a的地址:effb54 变量f的值:12.34 变量f的地址:effb48 */
-
指针类型
&a、&f的值都是地址,但&a、&f的类型是不f同的,&a指向整型变量a的指针,&f指向实型变量f的指针。
-
指针变量
如果把内存单元的地址用一个变量来保存,则这个变量称为指针变量。
-
数据在内存中的存取方式
① 直接通过变量名a对其进行存取。scanf("%d\n",&a)
② 通过指针变量p找到其所指的变量a,然后对所其指向的变量a进行存取操作。
-
指针变量的定义、初始化和引用
-
指针变量的定义和初始化
类型说明符 *指针变量名[=初值]; int a = 8, *p = &a;
-
指针变量的引用
&:取地址运算符,后面能接任何类型的变量(包括指针变量)
*:指针运算符,后面只能接指针变量
指针变量的赋值格式为:
指针变量名=&普通变量名; int a = 8, *p, *q; p = &a; q = p;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Eu0SiswN-1637485634415)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1637219313519.png)]
引用格式:
① *指针变量名——代表所指变量的值
② 指针变量名——代表所指变量的地址
int a, *p; p = &a; /*指针p指向了变量a的地址*/ *p = 8; /*相当于a=8*/
例子:
#include<stdio.h> int main() { int a = 8, b = 10; int* p = &a, * q = &b; printf("%d, %d\n", a, b); printf("%d, %d\n", *p, *q); return 0; } /* 8, 10 8, 10 */
指针的使用
-
指针的运算
- 指针的移动
- 指针的关系运算
-
指向简单变量的指针
指针变量的值=所指变量的地址,所指变量的地址不会因为其变量值的变化而变化。
-
指向指针变量的指针
类型说明符 **指针变量名[=初值] int a = 10, *p, **q; p = &a; q = &p; 或: int a = 10, *p = &a, **q = &p;
指针与数组
-
指向数组元素的指针
-
使指针变量指向"数组元素"的方法
int a[10], *p = &a[0], *q = &a[8]; 或: int b[2][4], *p = &b[0][0], *q = &b[1][3];
-
指向数组元素的指针变量的运算
p++,*(p++)
int a[3] = { 11,22,33 }; int* p = a, X; printf("给X赋值的语句执行前,p=%d\n", p); X = *p++; printf("X=%d\n", X); printf("给X赋值的语句执行后,p=%d\n", p); /* 给X赋值的语句执行前,p=20183244 X=11 给X赋值的语句执行后,p=20183248 */ int a[2][4] = { {80,81,82,83},{84,85,86,87} }; int* p = &a[0][0]; for (int i = 0; i < 8; i++) { printf("%3d", *(p + i)); } // 80 81 82 83 84 85 86 87
-
指针与一维数组
当指针p指向一维数组中某个元素a[i]后,可以用指针p访问一维数组的所有元素
int a[5],*p; p = a; 或: p = &a[0];
int a1 = 123, a2 = 234, a3 = 345, i; int* p1, * p2, * p3; int as[3] = { 1,2,3 }, * ps; p1 = &a1; p2 = p1 + 1; p3 = p2 + 1; printf("p1=%lu\tp2=%lu\tp3=%lu\n", p1, p2, p3); printf("a1=%d\t\ta2=%d\t\ta3=%d\n", a1, a2, a3); printf("*p1=%d\t\t*p2=%d\t*p3=%d\n",*p1,*p2,*p3); ps = as; for (i = 0; i < 3; i++) { printf("ps[%d]=%d\t\t", i, ps[i]); } printf("\n"); /* p1=10024696 p2=10024700 p3=10024704 a1=123 a2=234 a3=345 *p1=123 *p2=-858993460 *p3=605145006 ps[0]=1 ps[1]=2 ps[2]=3 只有指针p1是指向了变量a1的地址,而指针p2、p3并没有指向任何变量的地址,尽管有p2 = p1 + 1;、p3 = p2 + 1;这样的操作,但这并不意味着p2、p3指向了变量a2、a3的地址。 若指针访问越界,所指向的单元的值不确定 */
-
指针与字符串
char str[40] = "Computer"; char *sp = str;
① 下标法:sp[i]
② 首地址法:*(sp+i)
③ 指针变量法:*sp
char* sp = "Computer"; printf("%s", sp);//指针变量法 while (*sp!='\0') { printf("%c", *sp++);//首地址法 } /*Computer*/
-
指针与二维数组
int main() { int a[3][4] = { {1,2,3,4},{5,6,7,8},{9,10,11,12} }, * p; int i, j; for (p = a[0]; p < a[0]+12; p++) { if ((p-a[0])%4==0) { printf("\n"); } printf("%-4d", *p); } printf("\n"); printf("--------------\n"); for (i = 0; i < 3; i++) { for (j = 0; j < 4; j++) { printf("%-4d", *(a[i] + j)); } printf("\n"); } return 0; } /* 1 2 3 4 5 6 7 8 9 10 11 12 -------------- 1 2 3 4 5 6 7 8 9 10 11 12 */
-
-
指针数组
int main() { int a = 10, b = 20, c = 30, sum; int* p[3]; /*定义一个指针数组,数组元素是指向int型数据的指针*/ printf("a=%d,\t\tb=%d,\t\tc=%d\n", a, b, c); p[0] = &a; p[1] = &b; p[2] = &c;/*指针数组元素分别指向变量a、b、c*/ printf("*p[0]=%d,\t*p[1]=%d,\t*p[2]=%d\n", *p[0], *p[1], *p[2]); sum = *p[0] + *p[1] + *p[2]; /*引用指针数组元素所指变量的值*/ printf("*p[0] + *p[1] + *p[2]=%d\n", sum); printf("1p[0]=%p\n", p[0]); (*p[0])++; printf("a=%d,\t*p[0]=%d\n", a, *p[0]); printf("2p[0]=%p\n", p[0]); return 0; } /* a=10, b=20, c=30 *p[0]=10, *p[1]=20, *p[2]=30 *p[0] + *p[1] + *p[2]=60 1p[0]=00EFFBFC a=11, *p[0]=11 2p[0]=00EFFBFC */
第二个例子:
int main() { int i; char words[][16] = { "internet","times","mathematics","geography" }; char* pw[] = { words[0], words[1], words[2], words[3] }; char** ppw; ppw = pw; for (i = 0; i < 4; i++) { printf("%-15s", *ppw++); } printf("\n----------------------------------------------------------\n"); for (i = 0; i < 4; i++) { ppw = &pw[i]; printf("%-15s", *ppw); } return 0; } /* internet times mathematics geography ---------------------------------------------------------- internet times mathematics geography */
指针p和指向多个元素的指针t:
int main() { int a[3][4] = { {1,2,3,4},{5,6,7,8},{9,10,11,12} }; int* p, (*t)[4], i, j; p = a[0]; t = a; /* p、t均指向数组的首地址 */ for (i = 0; i < 3; i++) { for (j = 0; j < 4; j++) { printf("%d\t", *(*(t + i) + j)); } printf("\n"); } printf("p=%lu,*p=%d\n", p, *p); printf("t=%lu,**t=%d\n", t, **t); printf("--------------------\n"); p = p + 1; t = t + 1; printf("p=%lu,*p=%d\n", p, *p); printf("t=%lu,**t=%d\n", t, **t); printf("--------------------\n"); p = p - 1; t = t - 1; /*重新指向数组的首地址*/ printf("用指针p的移动输出数组元素:\n"); for (; p < a[0]+12; p++) { printf("%d ", *p); } printf("\n利用指针t的移动输出数组元素:\n"); for (; t < a + 3; t++) { for (j = 0; j < 4; j++) { printf("%d ", *(*t+j)); } } printf("\n"); return 0; } /* 1 2 3 4 5 6 7 8 9 10 11 12 p=14679720,*p=1 t=14679720,**t=1 -------------------- p=14679724,*p=2 t=14679736,**t=5 -------------------- 用指针p的移动输出数组元素: 1 2 3 4 5 6 7 8 9 10 11 12 利用指针t的移动输出数组元素: 1 2 3 4 5 6 7 8 9 10 11 12 */