当我在使用指针的时候,发现只要有对指针知识点有一点模糊的内容没有理解,就会导致后期使用的时候代码经常报错,因此我决定复习回顾之前指针所学内容,并且分享给大家,如果我有错误的地方和理解不到位的内容,还请大家指正。
一、新手如何理解指针?
1、指针的理解
-
指针就是地址,地址帮助我们在计算机中找到存储数据的位置
2、如何学习指针
在学习指针时,我通常就记住几个知识点,这样辅助我记忆和理解指针
-
变量 例如 int a;
-
常量 例如 10;
-
指针变量 例如 int * p; 指针p的数据类型是int *
-
取地址符 例如 &a;注意:取地址符不能用在常量上,只能用在变量上
-
取值符也叫解引用符 例如 *p; 注意 :取值符只能用在地址上,算术运算中的 * 表示乘法符号
-
数组 int arr[10] ; 注意:在C语言中,数组名表示数组元素的首地址;
拥有这些知识点之后,我们就能很好的理解指针了
int * p1;//定义指针变量p1, 可以存储int类型数据的首地址
char * p2;//定义指针你变量p2, 可以存储字符类型数据的首地址
指针的大小
32位操作系统的指针大小:4字节,32位
64位操作系统的指针大小:8字节,64位
3、指针的算术运算
指针也能进行算术运算,但是只能进行加法运算和减法运算,实际上就是地址的偏移
偏移大小时,指针指向类型的大小
int * p1;
p1 + 1, 指针指向int型数据的地址,偏移四个字节,地址 + 4
char * p2;
p2 + 1,偏移一个字节,地址 + 1
long * p3;
p3 + 1,偏移八个字节,地址 + 8 (OS为64位),偏移四个字节,地址 + 4(OS为32位)
指针-指针 表示两个指针之间的存储位置间隔距离
野指针:对于没有初始化的指针和没有赋值的指针,直接取地址,那么就使用野指针,会出现错误
万能指针:void *;
万能指针 void * ,可以存储任意类型的地址,也可以把void *类型的指针赋值给其他任意类型的指针变量
int a;
float b;
void * p = &a;
p = &b;
int * q = p;
万能指针占用 4/8字节空间存储地址,且只能存储地址,不能进行解引用(不能 *p ),因为指向类型为void,不知道解引用时需要访问几个字节,所以不能解引用
只能转换为其他类型指针进行使用
总结
int a;
&a 是什么类型?是变量还是常量?
int * 类型,常量
int * p = &a;
p是什么类型,*p是什么类型?
p是 int * 类型,*p是 int类型(就是a的空间),按照p的指向类型取大小
*&a == a
&、* 两个运算符 是逆运算
&a++ 和 p++
&a++ 错误的
p++,p指针变量 存储的是地址,p++,就是把地址向增大方向偏移一个单位,得到新的地址,然后存储到 p 指针变量中
*p++ 和 (*p)++
*p++ : 先算p++,然后取* 运算,运算p++的结果为p,,取* *p, 但是p += 1
(*p)++ : 先算 *p 得到 a,再进行++
*++p :先p+=1,然后把新的p的值,进行 取 *
p = 0x10;
*++p ====> ++p p = 0x14, *p= *(0x14)
为了防止学不会,请看下面的习题
一 、 选 择 题
1. 变 量 的 指 针 , 其 含 义 是 指 该 变 量 的 ____.
a)值 b)地 址
c)名 d)一 个 标 志
这题很简单,指针是地址,变量的指针就是变量的地址,选b
2. 若 有 语 句 int *point,a=4;和 point=&a;下 面 均 代 表 地 址 的 一 组 选 项 是 __ _.
a)a,point,*&a b)&*a,&a,*point
c)*&point,*point,&a d)&a,&*point ,point
这题我们只需要记住&,的用法
&a:是对变量a取值,在用&取a的值,这里的a是变量,不要认为是一个常量了。
&point :表示对指针变量取地址,再用取这个地址的值,取到的值是指针变量的地址,最后得到变量a的地址,不要理解错了,如果错了,看前面我说的取值符和取地址符的使用方法,还有要明确所取值的对象,这里用&符,取到了指针的地址,这个指针存的是变量地址,所以选d
3. 若 有 说 明 ;int *p,m=5,n;以 下 正 确 的 程 序 段 的 是 ________.
a)p=&n; b)p=&n;
scanf("%d",&p); scanf("%d",*p);
c)scanf("%d",&n); d)p=&n;
*p=n; *p=m;
这里使用scanf函数,要用到&符,但是%d明确是一个整型,a,b错误
c选项使用了野指针,P没有初始化和赋值,直接取值;选d,*p是变量,能进行赋值操作
4. 以 下 程 序 中 调 用 scanf 函 数 给 变 量 a 输 入 数 值 的
方 法 是 错 误 的 , 其 错 误 原 因 是__ _____.
main()
{
int *p,*q,a,b; p=&a; printf(“input a:”); scanf(“%d”,*p);
… …
}
a)*p 表 示 的 是 指 针 变 量 p 的 地 址
b)*p 表 示 的 是 变 量 a 的 值 , 而 不 是 变 量 a 的 地 址
c)*p 表 示 的 是 指 针 变 量 p 的 值
d)*p 只 能 用 来 说 明 p 是 一 个 指 针 变 量
看代码,直接选b,选其他的请去多学
5. 已 有 变 量 定 义 和 函 数 调 用 语 句 : int a=25; print_value(&a);
下 面 函 数 的 正 确 输出 结 果 是 ______.
void print_value(int *x)
{
printf(“%d\n”,++*x);
}
a)23 b)24 c)25 d)26
这里我们可以理解为的运算优先级比++高,先计算取值符,把x进行++操作选d;
6.若 有 说 明 : long *p,a;则 不 能 通 过 scanf 语 句
正 确 给 输 入 项 读 入 数 据 的 程 序 段 是
A) *p=&a; scanf("%ld", p);
B) long int a ; p=(long *)&a; scanf("%ld", p);
C) scanf("%ld", p=&a);
D) scanf("%ld", &a);
选a,*p是野指针错误了,其他项是正确项,可以理解一下
7.有 以 下 程 序#include<stdio.h> main()
{ int m=1,n=2,*p=&m,*q=&n,*r; r=p;p=q;q=r; printf("%d,%d,%d,%d\n",m,n,*p,*q);}
A) 1, 2, 1, 2 B) 1, 2, 2, 1
C) 2, 1, 2, 1 D) 2, 1, 1, 2
这里对指针所指向的数据进行了交换,选b
8. 有 以 下 程 序
main()
{ int a=1, b=3, c=5;
int *p1=&a, *p2=&b, *p=&c; *p =*p1*(*p2); printf("%d\n",c);
}执 行 后 的 输 出 结 果 是
A) 1 B) 2 C) 3 D) 4
选C,(*p2)相当于一个变量,等于3;p1取值乘以p2取值=3
9. 有以下程序main(){
int a,k=4,m=4,*p1=&k,*p2=&m;a=p1==&m;printf("%d\n",a);}
程 序 运 行 后 的 输 出 结 果 是
A 、4 B、 1 C 、0 D、 运 行 时 出 错 , 无 定 值
这里先计算p1==&m,这两个地址不一样,比较结果为0
a=0;选c
10. 在 16 位 编 译 系 统 上 ,若 有 定 义 int a[]={10,20,30}, *p=&a;, 当 执 行 p++;后 ,
下 列 说 法 错 误 的 是 ( )
A) p 向 高 地 址 移 了 一 个 字 节 B) p 向 高 地 址 移 了 一 个 存 储 单 元
C) p 向 高 地 址 移 了 两 个 字 节 D) p 与 a+1 等 价
选a,16位移动两个字节
如果以上都正确的话,你的实力已经接近我了,但是还是得练,毕竟,菜就多练,如果正确率太低,不要着急,去看其他大佬的文章,也能学到东西