当然如果我们将 & arr[9] - &arr[0] 的顺序调换以下,变成 & arr[0] - &arr[9],得到的又是什么呢?
结果是: - 9
所以如果我们要得到元素的个数,应该用大地址 - 小地址。
看下面这个 错误做法:
指针 + - 要使他们都指向一个空间
练习:模拟strlen的功能函数 (第三种方法)–>见’ 递归 ’
int my_strlen(char* str) { char* start = str; char* end = str; while (*end != '\0') { end++; } return end - start; } int main() { char arr[] = "hello,world"; int len = my_strlen(arr); printf("%d", len); return 0; }
③指针的关系运算
关系运算,简单来说就是比较大小,有 > 、 >= 、 == 、 != 、 < 、 <=
看下面例子:
#define N_VALUES 5 float values[N_VALUES]; //代表右5个元素 float *vp; //指针+-整数;指针的关系运算 for (vp = &values[N_VALUES]; vp > &values[0];) { *--vp = 0; }
将上面代码改造一下↓↓↓↓↓
for(vp = &values[N_VALUES-1]; vp >= &values[0];vp--) { *vp = 0; }
实际在绝大部分的编译器上是可以顺利完成任务的,然而我们还是应该避免这样第二种写,因为标准并不保证它可行。
标准规定∶
允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。
这句话看到这里,还是不太明白,所以就画个图来演示一下:
(画图演示很重要)
5.数组和指针
数组名是什么?
在之前的学习中,我们可能已经知道了数组名就是首元素的地址,这里我们验证一下这个说法是否正确,请看下面这个例子:
可以看到 arr 和& arr[0] 结果是一样,说明 “数组名就是首元素的地址” 是正确的!
但是,数组名就一直是首元素地址吗?
数组名在绝大多数情况下是首元素地址,但有两个例外:
1、& arr — &数组名 - 数组名不是首元素的地址,数组名表示整个数组 &
数组名 , 取出的是整个数组的地址。
整个数组的地址和首元素地址有什么区别呢?
2、sizeof(arr)----sizeof(数组名)-- - 数组名表示的整个数组–sizeof(数组名)计算的是整个数组的大小。
我们回到刚刚说的问题:整个数组的地址和首元素地址有什么区别呢?
在打印的时候我们发现打印出来的值是相等的。
解析:
举例:我们让它们都进行 + 1, 首元素地址加1就到了第二个元素的地址,而数组地址 + 1则是直接跳过该数组
上面我们说了 数组名就是首元素的地址,那么我们通过使用指针来访问数组就成为了可能:
#include<stdio.h> int main() { int arr[] = { 1,2,3,4,5,6,7,8,9,10 }; int* p = arr; int i = 0; int sz = sizeof(arr) / sizeof(arr[0]); for (i = 0; i < sz; i++) { printf("&arr[%d] = %p <===> p+%d = %p\n", i, &arr[i], i, p + i); } return 0; }
p + i其实计算的是数组arr下标为i的地址。那么我们就可以直接通过指针来访问数组,比如:
6.二级指针
指针变量也是变量,是变量就有存储空间,就有地址,那么指针变量的地址存放在哪里那?
这就是二级指针,指向内容是存放地址的指针。
通常我们所说的指向数组的指针是一级指针。
#include<stdio.h> int main() { int a = 10; int* pa = &a;//pa 一级指针 int** ppa = &pa;//ppa 二级指针 ......后面还有 三级指针、四级指针....n级指针 return 0; }
这里我们进行画图演示:
好了,现在我们对二级指针应该理解清楚了,但是二级指针怎么应用呢?
如果我们对 ppa 进行解引用操作 * ppa就 能找到 pa 也就是a的地址,再次进行解引用操作** ppa,就能找到a了!
如下图:
7.指针数组
在我们学习指针和数组的概念时,会接触到两个这样的概念
1.指针数组-- - 数组-- - 存放指针的数组
2.数组指针-- - 指针
那么我们怎么来理解1.指针数组呢?我们来看下面的这个问题。
#include<stdio.h> int main() { int a = 10; int b = 20; int c = 30; int* pa = &a; int* pc = &c; //这里只有三个变量,我们创建了三个指针分别存放它们的地址 //假如有10个变量,我们要一口气创建10个指针来存放它们的地址吗? return 0; }
这个时候我们就会思考,这10个指针变量能不能利用数组的方式来创建呢,就跟10个int 类型的变量一样,通过创建一个 int arr[10]就能实现。
整型数组-- - 存放整型
字符数组-- - 存放字符
指针数组-- - 存放指针
按照这个思路,我们创建一个指针数组 int* arr[3] = { &a,&b,&c };
我们可以通过指针数组访问其内容并打印: