如何学好c语言指针(1)
2024-01-03 15:23:58
开始学习前,先说明一下,下述所写代码均是伪代码哦。
1.记住这句话:指针==地址==内存单元的编号,指针就是用来存地址的。
2.取地址符(&)
int n;
&n;//通过取地址符&可以得到n的地址
3.指针变量和解引用操作符(*)
int *p=NULL://初始化指针变量p
//----------------------------
int a=10;
int *p=&a;//用指针变量p存放a的地址
printf("%d",*p);//p中存放的是a的地址,*p解引用得到a中的数据,即*p=10;
//值得补充的是,解引用可以修改指针指向的地址的内容,如上述可以*p=0,a的值也就为0了,可以运用在跨
//函数修改值的情况下
int a=10;
int *p=&a;//用指针变量p存放a的地址
*p=0;
printf("%d",a);//p中存放的是a的地址,*p解引用修改了a中的数据,即a==*p==0;
//-----------------------------------------
void test(int *p) //跨函数的情况下
{
*p=0;//*p将a中的值修改为0
}
int main()
{
int a=10;
test(&a);
printf("%d",a);//此时a==0;
4.指针变量的大小
无论什么类型的指针,如char *p;int *p;double *p。这些指针的大小但是相同的,在32位的操作系统下是4个字节的大小,在64位的操作系统下是8个字节的大小。
5.指针变量类型的意义
(1)解引用时不同
int n=0x11223344;
int *pa=&n;
*pa=0;
printf("%x",n);//n=0x00000000;
//--------------------------
int n=0x11223344;
char *pb=&n;
*pb=0;
printf("%x",n);//n=0x00223344;
(2)加减时不同
int n=10;//假设n的地址是0x00000001
int *pa=&n;
char *pb=&n;
printf("%p",&n);//&n=0x00000001;
printf("%p",pb+1);//pb+1=00000002;//指针类型决定了加减的大小,如char*加减1位,int*加减4位
printf("%p",pa+1);//pa+1=00000005;
(3)特殊指针类型(void*)
void*指针类型不能进行加减运算,也不能进行解引用运算,void*的指针该如何使用呢?
?般 void* 类型的指针是使?在函数参数的部分,?来接收不同类型数据的地址,这样的设计可以 实现泛型编程的效果。使得?个函数来处理多种类型的数据。处理时用强制类型转换即可。日后遇见就明白了。
6.const修饰指针
const说白了就是保持数据不变的作用。
//-----------------------------------------------
//第一种情况,const在*前
int n=0;
int *p=&n;
*p=10;//ture
printf("%d",n);//n被修改为10
int n=0;
const int *p=&n;
*p=10;//error,此时会报错,const修饰后,解引用只能是n=0,不能再修改
printf("%d",n);p
//-----------------------------------------------
//第二种情况,const在*后
int m=0;
int n=0;
int *p=&m;
p=&n;//ture
printf("%p",&m);
printf("%p",&n);
printf("%p",p);//p指向的是n的地址
int m=0;
int n=0;
int * const p=&m;
p=&n;//error,此时会报错,const修饰后,p只能指向m的地址,不能再指向其它的地址
printf("%p",&m);
printf("%p",&n);
printf("%p",p);
//-----------------------------------------------
//第三种情况,const既在*前,也在*后
//也就是前两种情况的结合,不能解引用修改值,也不能改变指向的地址,这里不再赘述。
//-----------------------------------------------
//补充不是指针的情况下
int n=0;
n=10;//ture
const int n=0;
n=10;//error,此时会报错,const修饰后,变量也不可更改
7.指针的运算
(1)加减运算:就是根据指针类型加减不同的大小,前面讲过,这里不再赘述。
(2)指针-指针:就是指针之间字节数目的差值。
(3)指针大小的判断:&a=0x00000001,&b=0x00000002,&a<&b,根据指针指向的地址大小来判断。
8.野指针
(1)局部指针未初始化,默认为随机值。如:
#include <stdio.h>
int main()
{
int *p;//局部变量指针未初始化,默认为随机值,应当int *p=NULL;
*p = 20;
return 0;
}
(2)越界访问
int a[10]={0};
int *p=a[10];//数组a只有a[0]到a[9],此时越界了
(3)指针指向的地址被释放
void stm()
{
int a=10;
return &a;
}
int main()
{
int *p=stm();//a是局部变量,在stm()函数结束时已经被销毁了,&a已经不存在了
return 0;
}
9.野指针的避免
(1)初始化时给确切的地址或赋NULL
int *p=NULL;
//或者
int a=10;
int*p=&a;
(2)避免越界访问
(3)避免接受返回的局部变量的地址
(4)当用完指针时,习惯将指针置NULL,习惯使用指针时检查指针的有效性。
10.assert断言
assert(表达式),若表达式为假,系统会报错。常用于判断指针是否非空。若不需要,只需加宏定义#define NDEBUG即可,系统默认assert语句无效。所需头文件为assert.h。缺点就是多了代码,就多耗费时间。
博主本人也是菜鸟,这些是我学习后总结出来的知识点,希望可以帮到大家,大家互相学习,共同进步。欢迎大家指出错误。
文章来源:https://blog.csdn.net/2301_79819250/article/details/135348347
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!