赞
踩
一些概念:
p++和p+i不同,p+1只是指针向后移一位,此时p本身指向的值不变,p++则是p指向它后一位指针指向的值。而传递进函数的数组地址a[2]则代表*(p+2)指针原本地址没变。
指针是一种数据类型,占用内存空间,用来保存内存地址。
void test01(){ int* p1 = 0x1234; int*** p2 = 0x1111; printf("p1 size:%d\n",sizeof(p1)); printf("p2 size:%d\n",sizeof(p2)); //指针是变量,指针本身也占内存空间,指针也可以被赋值 int a = 10; p1 = &a; printf("p1 address:%p\n", &p1); printf("p1 address:%p\n", p1); printf("a address:%p\n", &a); } |
不允许向NULL和非法地址操作内存:俩种非法操作(拷贝内存,取地址等)
void test(){//不能向空指针中拷贝内存 char *p = NULL; //给p指向的内存区域拷贝内容 strcpyp, "1111"); //err(strcpy本质就是首地址到\0然后黏贴到另一个地址) char *q = 0x1122;//不能向野指针中拷贝内存 //给q指向的内存区域拷贝内容 strcpy(q, "2222"); //err } |
2.1 空指针
概念:标准定义了NULL指针,它作为一个特殊的指针变量,表示不指向任何东西。要使一个指针为NULL,可以给它赋值一个零值。为了测试一个指针百年来那个是否为NULL,你可以将它与零值进行比较。
对指针解引用操作可以获得它所指向的值。但从定义上看,NULL指针并未指向任何东西,因为对一个NULL指针因引用是一个非法的操作,在解引用之前,必须确保它不是一个NULL指针。
如果对一个NULL指针间接访问会发生什么呢?结果因编译器而异。
2.2 野指针(野指针具体情况得看编译器,有时候会小幅度允许编译通过,但是尽量规避)
概念:野指针指向一个已删除的对象或未申请访问受限内存区域的指针。与空指针不同,野指针无法通过简单地判断是否为 NULL避免,而只能通过养成良好的编程习惯来尽力减少。对野指针进行操作很容易造成程序错误。在使用指针时,要避免野指针的出现
野指针类型:什么情况下回导致野指针?
解决方法:操作野指针是非常危险的操作,应该规避野指针的出现:
1.初始化时置 NULL 指针变量一定要初始化为NULL,因为任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的。 2.释放时置 NULL 当指针p指向的内存空间释放时,没有设置指针p的值为NULL。delete和free只是把内存空间释放了,但是并没有将指针p的值赋为NULL。通常判断一个指针是否合法,都是使用if语句测试该指针是否为NULL。 3.不要返回指向栈内存的指针或引用 因为栈内存在函数结束时会被释放。 |
概念:
指针是一种数据类型,是指它指向的内存空间的数据类型。指针所指向的内存空间决定了指针的步长。指针的步长指的是,当指针+1时候,移动多少字节单位。
思考如下问题:
int a = 0xaabbccdd; unsigned int *p1 = &a; unsigned char *p2 = &a; //为什么*p1打印出来正确结果? printf("%x\n", *p1); //为什么*p2没有打印出来正确结果? printf("%x\n", *p2); //为什么p1指针+1加了4字节? printf("p1 =%d\n", p1); printf("p1+1=%d\n", p1 + 1); //为什么p2指针+1加了1字节? printf("p2 =%d\n", p2); printf("p2+1=%d\n", p2 + 1); |
1.指针变量+1后跳跃的地址字节数(根据数据类型跳)
2.步长是解引用取出的字节数(根据数据类型取地址)可以强转类型跳步取值
练习:
打印函数偏移量
小结:
对自定义数据类型进行练习
- 如果获取自定义数据类型中属性的偏移
- offsetof( 结构体 , 属性 )
- 头文件 #include<stddef.h>
通过指针间接赋值成立的三大条件:
1. 2个变量(一个普通变量一个指针变量、或者函数一个实参一个形参) 建立关系
2.通过 * 操作指针指向的内存
void test(){ int a = 100; //两个变量 int *p = NULL; //建立关系 //指针指向谁,就把谁的地址赋值给指针 p = &a; //通过*操作内存 *p = 22; } |
void test(){ int b; int *q = &b; //0级指针 int **t = &q; int ***m = &t; } |
int func1(){ return 10; } void func2(int a){ a = 100; } //指针的意义_间接赋值 void test02(){ int a = 0; a = func1(); printf("a = %d\n", a); //为什么没有修改? func2(a); printf("a = %d\n", a); } //指针的间接赋值 void func3(int* a){ *a = 100; } void test03(){ int a = 0; a = func1(); printf("a = %d\n", a); //修改 func3(&a); printf("a = %d\n", a); } |
void AllocateSpace(char** p){ *p = (char*)malloc(100); strcpy(*p, "hello world!"); } void FreeSpace(char** p){ if (p == NULL){ return; } if (*p != NULL){ free(*p); *p = NULL; } } void test(){ char* p = NULL; AllocateSpace(&p); printf("%s\n",p); FreeSpace(&p); if (p == NULL){ printf("p内存释放!\n"); } } |
概念:指针做函数参数,具备输入和输出特性:
在主调函数中分配内存空间,被调函数传参,进行内存使用(被调函数形参用一级指针修饰)
分为栈上分配和堆上分配
void fun(char *p /* in */) { //给p指向的内存区域拷贝内容 strcpy(p, "abcddsgsd"); } void test(void) { //输入,主调函数分配内存 char buf[100] = { 0 }; fun(buf); printf("buf = %s\n", buf); } |
在被调函数中分配内存空间,内存使用(被调函数形参用二级指针修饰)
void fun(char **p /* out */, int *len) { char *tmp = (char *)malloc(100); if (tmp == NULL) { return; } strcpy(tmp, "adlsgjldsk"); //间接赋值 *p = tmp; *len = strlen(tmp); } void test(void) { //输出,被调用函数分配内存,地址传递 char *p = NULL; int len = 0; fun(&p, &len); if (p != NULL) { printf("p = %s, len = %d\n", p, len); } |
小结:
1.越界
一共四个只存了3,\0没存,造成打印错误乱码
void test(){ char buf[3] = "abc"; printf("buf:%s\n",buf);一共四个只存了3,\0没存,造成打印错误乱码 } |
2.指针叠加会不断改变指针指向
释放掉的指针位置已经改变了,不是原先的了,释放编译不通过报错
要使用临时指针进行偏移操作
void test(){ char *p = (char *)malloc(50); char buf[] = "abcdef"; int n = strlen(buf); int i = 0; for (i = 0; i < n; i++) { *p = buf[i]; p++; //修改原指针指向 } free(p);//释放掉的指针位置已经改变了,不是原先的了,释放编译不通过 } |
更改正确写法: 再引出一个指针去实现操作,原指针就不动了
当函数执行完,时候后,局部变量不存在,地址变成乱码
char *get_str() { char str[] = "abcdedsgads"; //栈区, printf("[get_str]str = %s\n", str); return str;当函数执行完,时候后,局部变量不存在,地址变成乱码 } |
(结果不重要,乱码和报错看编译器)
void test(){ char *p = NULL; p = (char *)malloc(50); strcpy(p, "abcdef"); if (p != NULL) { //free()函数的功能只是告诉系统 p 指向的内存可以回收了 // 就是说,p 指向的内存使用权交还给系统 //但是,p的值还是原来的值(野指针),p还是指向原来的内存 free(p); } if (p != NULL) { free(p); } } |
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。