所有笔记省略了我认为在基础阶段必须掌握的内容,诸如部分的名词、符号定义以及用法
1 指针的使用
1.1 了解指针
指针可以理解为保存地址的变量。
下方countPtr指针变量的值是内存中的地址。(也就是说指针变量的值是具有实际值的变量的地址,有点饶人就多看几遍!)
int i; int *p=&i; int *p,q; //这里到底定义了几个指针变量,需要好好体会!
如何访问指针的值
int k=*p; *p=k+1;
*用来访问指针所指向的对应的变量的值,可以在右边(右值),也可以在左边(左值),同学们需要体会两者的差异。
1.2 指针的应用场景
场景一:通过指针交换两个变量的值
交换两个值可以通过多种方式来实现,在许多排序算法中也用到了交换。我们要再函数中实现对变量值修改并且在main函数中也要生效,所以要使用指针对对应的变量的值进行修改。
void swap(int *pa,int *pb) { int temp=*pa; *pa=*pb; *pb=temp; }
场景二:函数需要返回多个值
大家都知道return一次只可以返回一个值,若需要返回多个值时,我们可以考虑使用指针来实现。
场景二下有一种略显特殊带实际中容易碰到的情况,我们一般习惯于在函数内完成所有操作返回计算结果,碰到异常时返回状态(-1或0)。
int positive(int a) { if(a>0) return 1; else return 0;//返回-1也可以 } //我简单想了一个判断正数的小例子,这里的return 0、-1就是返回到主函数一个异常态
但是有时我们需要返回的值的结果中可能包含了我们可能要存在的这种异常态,这样主函数想要对结果进行操作,就会存在歧义。
解决方案:函数返回运算的状态,结果通过指针来返回
1.3 数组变量是特殊的指针
光看标题其实很难理解,数组变量相较指针究竟特殊在哪里呢?
int a[]={1,2,3,4}; int *p=a; printf("%d",*(++p)); //output:2
int a[]={1,2,3,4}; printf("%d",*(++a); //报错
具体如何鉴别请参考下面一节
1.4 指针与const
上面的数组a中的a其实就是一个常量指针,也就是一旦a得到了某个变量的地址,便不能再指向其他变量,我们可以改变指针变量所对应的值,但无法改变指针指向,请见下方例子。
int *const q=&i; //q是const *q=26;//ok q++; //error
区别:
下面是const在最外侧的情况,表示不能通过这个指针去修改那个变量。
const int *p=&i; *p=26;//error (*p)是const i=26; //ok p=&j; //ok
作用:
把数组传入函数时传递的是地址,所以那个函数内部可以修改数组的值。为了保护数组不被函数破坏,可以设置参数为const。
课堂交流区精华
老师说数组变量可以被看作是const的指针变量,到底是“可以被看作”,还是“就是”指针呢?
用程序证据(而不是搜索教科书)来说明你的观点。
(提示:如果对const指针的所有的操作都可以对数组变量做,而且结果一致,就说明数组变量就是指针;如果有某个操作不能做,或者结果不一致,就说明不是指针)
1: int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; for(i = 0; i < len; i++) printf("%d ", *a++); //编译错误,说明数组应该是int* const,而不是const int* -------------------------------------------------------------------------------------------------------------------------------- 2: int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int * const p = a; printf("sizeof(a) = %d\n", sizeof(a)); printf("sizeof(p) = %d\n", sizeof(p)); /* 32系统下运行结果: sizeof(a) = 40 sizeof(p) = 4 说明 int a[] 在主函数中有数组所有元素的大小,而 int* const 只是一个指针*/ ---------------------------------------------------------------------------------------------------------------------------------- 3: p = a; //编译出错 说明int* const只能在定义是初始化,即:int * const p = a; ---------------------------------------------------------------------------------------------------------------------------------- 4: 其他操作功能相同,比如:a[i]与p[i] 、*(a+i)与*(p+i)。附上具体代码如下: #include <stdio.h> int main(void) { int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int * const p = a; printf("sizeof(a) = %d\n", sizeof(a)); printf("sizeof(p) = %d\n", sizeof(p)); printf("\n"); printf("a = %p\n", a); printf("p = %p\n", p); printf("\n"); int i, len; len = sizeof(a)/sizeof(a[0]); printf("a[i] print:\n"); for(i = 0; i < len; i++) printf("%d ", a[i]); printf("\np[i] print:\n"); for(i = 0; i < len; i++) printf("%d ", p[i]); printf("\n\n"); // printf("*a++ print:\n"); // for(i = 0; i < len; i++) // printf("%d ", *a++); //编译错误,说明数组应该是int* const而不是const int* // printf("\n"); // printf("*p++ print:\n"); // for(i = 0; i < len; i++) // printf("%d ", *p++); // printf("\n"); // printf("p = %p\n", p); // printf("\n"); // p = a; // printf("p = a, p = %p\n", p); printf("*(a+i) print:\n"); for(i = 0; i < len; i++) printf("%d ", *(a+i)); printf("\n"); printf("*(p+i) print:\n"); for(i = 0; i < len; i++) printf("%d ", *(p+i)); printf("\n\n"); a[0] = 100; printf("a[0] = %d\n", a[0]); for(i = 0; i < len; i++) printf("%d ", a[i]); printf("\n"); p[0] = 200; printf("p[0] = %d\n", p[0]); for(i = 0; i < len; i++) printf("%d ", a[i]); printf("\n"); printf("\n"); *a = 101; printf("*a = %d\n", *a); for(i = 0; i < len; i++) printf("%d ", a[i]); printf("\n"); *p = 201; printf("*p = %d\n", *p); for(i = 0; i < len; i++) printf("%d ", a[i]); printf("\n"); printf("\n"); *(a+2) = 101; printf("*(a+2) = %d\n", *(a+2)); for(i = 0; i < len; i++) printf("%d ", a[i]); printf("\n"); *(p+2) = 201; printf("*(p+2) = %d\n", *(p+2)); for(i = 0; i < len; i++) printf("%d ", a[i]); printf("\n"); return 0; }
课后好题
下面几题需要大家好好体会,务必搞懂!