南哪 2022-8-pointer
这一章的内容实际上在题单《逃不掉的语法小技巧 指针》当中已经讲的差不多了,不过我们在这里还需要补充一些东西。
在上一次介绍中我们在文末说到了这样一段话:
顺带一提,我们知道数组的名字就是指向它第一个元素的指针,那么数组到底是什么意思呢?
原来,数组后面方括号里面的数字实际上指的是相对于这个数组指针在内存上的偏移值,偏移 0 那就是第一个元素,偏移 1 那就是第二个元素,以此类推。
由这句话我们知道了数组名字是个指针,而且它实际上指向了数组的第一个元素。
我们都清楚这次的 OJ 十分的阴间,不允许使用 []
来调用数组的某一位,甚至不让用 []
开数组。
这怎么能忍!这就告诉你们 dotOJ
究竟在搞什么花样!
在第二题当中,我们需要开一个长度为 100000 的字符数组,我们就拿它来举例。
首先,我们使用malloc来申请内存,具体如下:
//别忘了包含stdlib.h
char *s = (char *)malloc(100000 * sizeof(char));
申请完以后我们就可以使用s[i]来调用s数组的第i位了,但是显然题目不允许我们这样做,怎么办呢?
我们注意到上面的malloc申请的实际上是一段连续的内存(不然没法调用数组的任意一个位置),所以我们可以尝试修改指针指向的地址来访问这个数组的任意一个位置。
比如说我们想要输出这个字符数组:
int len = strlen(s);
for (int i = 0; i < len; ++i)
putchar(*(s + i));//相当于s[i]
putchar('\n');
虽然这很好理解,但抛开好理解不谈,我们还是得好好理解为什么可以这样写(
当然还有第一题我们需要提到的指针问题:
既然存储数据都是 32 位,那么我们为什么不用不同的指针指向同一个 32 位呢?
而且题目也解释的很清楚,一开始只是平平无奇的一个 int,你只需要一位一位读入二进制然后把它弄到一个 int 里面
当然,实际上建议弄到 unsigned int 里面先搞,因为如果你没有学过之前学到的位运算,单纯用加法的话,int 的符号位可能会让你很头疼。
当我们搞好这个 unsigned int 变量的值,我们用不同数据类型的指针指向这个变量(当然都需要是 32 位存储的变量)
也就是分别用一个 int、一个 unsigned int、一个 float 指针指向这个 unsigned int 变量的存储位置,然后分别按要求输出就行了。
这样做的原理是什么呢?
因为内存总归是一位一位的,它很实在不会骗你,但是不同的变量类型理解内存上每一位的方式不一样,导致最终的结果就不一样。所以说,当我们用不同变量类型的指针指向同一个 32 位内存,它们理解内存的方式不同,导致你输出它们指向的变量的结果也就不同,这就是第一题想考察的地方。
指针真的就没有了,如果想寻求些挑战,你可以去看看之后出来的指针EX。
题单链接:
南哪2022-8-pointer - 题单 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
然而并没有题可以写(