- 指针的使用
- 传入函数得数组组成了什么
- 指针与const
- 指针运算
- 指针的类型
- 动态内存分配
- 指针能做什么
- 需要传入较大的数据时用作参数
- 传入数组后对数组做操作
- 函数返回不止一个结果
- 用函数来修改不止一个变量
- 动态申请的内存
应用场景
-
应用场景一
- 交换两个变量
#include
void swap(int *pa, int *pb); int main(void) { int a = 5; int b = 6; swap(&a, &b); printf("a=%d,b=%d", a, b); return 0; } void swap(int *pa, int *pb) { int t = *pa; *pa = *pb; *pb = t; } -
应用场景二
- 函数返回多个值,某些值就只能通过指针返回
- 传入的参数实际上是需要保存带回的
#includevoid minmax(int a[], int len, int *min, int *max); int main(void) { int a[] = {1,14, 65,265,262,3232,8,2,4,561,5,}; int min, max; minmax(a, sizeof(a) / sizeof(a[0]), &min, &max); printf("min=%d,max=%dn", min, max); return 0; } void minmax(int a[], int len, int *min, int *max) { int i = 0; *min = *max = a[0]; for (int i = 1; i < len; i++) { if (a[i] < *min) { *min = a[i]; } if (a[i] > *max) { *max = a[i]; } } }
-
应用场景二b
- 函数返回运算的状态,结果通过指针返回
- 常用的套路是让函数返回特殊得不属于有效范围内得值来表示出错,但是当任何数值都是有效得可能结果时就得分开返回了
- 后续的语言(C++、Java)采用异常机制来解决这个问题
#include
int devide(int a, int b, int *result); int main(void) { int a = 5; int b = 2; int c; if (devide(a, b, &c)) { printf("%d/%d=%dn", a, b, c); } return 0; } int devide(int a, int b, int *result) { int ret = 1; if (b == 0) { ret = 0; } else { *result = a / b; } return ret; }
- 函数参数表中的数组实际上是指针
sizeof(a)==sizeof(int*)
-但是可以用数组的运算符[]经行运算
- 指针不可修改 const在*后
- 不可通过指针修改 const在*前
const int* p1 = &i; //不能通过指针修改 int const* p2 = &i; 不能通过指针修改 int *const p3 = &i; 指针不能被修改
- 转换
- 总是可以把一个非const的值转换成const的
- 当要传递的参数的类型比地址大的时候,这是常用的手段:既能用比较少的字节数传递给参数,又能避免函数对外面的变量的修改
- const数组
- const int a[] ={1,2,3,4,5,6};
- 数组变量已经是const的指针,这里的const表明数组的每个单元都是const int
- 所以必须通过初始化经行赋值
- const数组可以用于保护数组值:因为把数组传入函数时传递的是地址,所以那个函数内部可以修改数组的值,为了保护数组不被函数修改,可以设置参数为const。
int sum(const int a[],int length);
- 常见错误:定义了指针变量,还没有指向任何变量,就开始使用指针。解决方案:在定义指针时,使指针指向NULL
- 给一个指针加1表示要让指针指向下一个变量
- 如果指针不是指向一片连续分配的空间,如数组,则这种运算没有意义
//*(p+1)--->a[1] int a[10]; int *p=a;
- 算术运算可以对指针做:
- 加减一个整数(+,+=,-,-=)
- 递增递减(++/--)
- 两个指针相减
- *p++
- 取出p所指的数据,完事后顺便把p移到下一个位置
- *的优先级虽然高,但是没有++高
- 常用于数组类的连续空间操作
- 在某些CPU上,这可以直接被翻译成一条汇编指令
- 指针比较
- <,<=,==,>,>=,!=都可以对指针做
- 比较他们在内存中的地址
- 数组中的单元地址肯定是线性递增的
- 0地址
- 内存中有0地址,但是0地址通常是个不能随便碰的地址,所以指针不应该具有0值
- 因此可以用0地址来表示特殊的事情:
- 返回的指针是无效的
- 指针没有真正被初始化
- NULL是一个预定定义的符号,表示0地址
- 有的编译器不愿意你用0来表示0地址
无论指向什么类型,所有的指针的大小都是一样的,因为都是地址,但是为了避免用错指针,指向不同类型的指针是不能直接互相赋值的
动态内存分配用于输入数组:如果输入数据时,先告诉你个数,然后再输入,要记录每个数据
int *a = (int*)malloc(n*sizeof(int));
- malloc
- # include
- void* malloc(size_t size);
- 向malloc申请的空间的大小是以字节为单位的
- 没空间:如果申请失败则返回0,或者叫做NULL
//malloc动态内存分配 #include
#include int main(void){ int number; int *a; int i; printf("输入数量:"); scanf("&d",&number); //int a[number]; C99 a = (int*)malloc(number*sizeof(int)); for(i=0;i =0;i--){ printf("%d",a[i]); } free(a); return 0; } - # include



