葫芦岛长城建设公司网站,自己怎么开网店的步骤,宝塔建站系统,商城网站大概多少钱目录 一、指针的运算
1.1指针 - 整数
1.2指针 - 指针
二、指针遍历数组
2.1指针遍历数组
1.了解数组名称的含义#xff08;数组名和数组名的区别#xff09;。
2.用指针遍历数组
三、指针数组、数组指针、函数指针
3.1指针数组
3.1.1指针数组的形式
3.1.2指针…目录 一、指针的运算
1.1指针 - 整数
1.2指针 - 指针
二、指针遍历数组
2.1指针遍历数组
1.了解数组名称的含义数组名和数组名的区别。
2.用指针遍历数组
三、指针数组、数组指针、函数指针
3.1指针数组
3.1.1指针数组的形式
3.1.2指针数组的使用案例
3.2数组指针
3.3函数指针
三、函数指针数组
3.1函数指针数组的形式
3.2函数指针数组的用途转移表
四、数组作为函数体参数
五、函数中用数组作为返回值
5.1返回静态局部数组的地址
5.2返回文字常量区的字符串的地址
5.3返回堆内容的地址
5.4总结 一、指针的运算
1.1指针 - 整数 总结指针的类型决定了指针向前或者向后走一步有多大距离。 1.2指针 - 指针
int main()
{int arr[10] { 0 };printf(%d\n, arr[9] - arr[0]);return 0;
} 当我们想用两个指针相减时从上图我们可以猜测一下输出的到底是两地址之间的元素个数还是两个地址的差值byte呢
通过运行我们可以知道指针 - 指针的结果指针和指针之间的元素个数。
那么任何两个指针都可以相减吗从上面的答案我们就可以得到 指针 - 指针的前提两个指针指向同一块区域指针类型是相同的。 那么如果用小指针 - 大指针我们的结果就成了 -9 .
所以我们可以得到更严谨一些的结论 指针 - 指针的结果其绝对值为指针与指针之间的元素个数。 二、指针遍历数组
2.1指针遍历数组
1.了解数组名称的含义数组名和数组名的区别。 数组名是数组首元素的地址。有两个例外 1. sizeof( 数组名 ) 计算整个数组的大小 sizeof 内部单独放一个数组名数组名表示整个数组。 2. 数组名取出的是数组的地址。 数组名数组名表示整个数组。 除此 1,2 两种情况之外所有的数组名都表示数组首元素的地址。 我们来看一段代码了解数组名和数组名的差别。
int main()
{int arr[10] { 0 };printf(arr %p\n, arr);printf(arr %p\n, arr);printf(arr1 %p\n, arr1);printf(arr1 %p\n, arr1);return 0;
} 根据上面的代码我们发现其实 arr 和 arr 虽然值是一样的但是意义应该不一样的。 实际上 arr 表示的是 数组的地址 而不是数组首元素的地址。 数组的地址 1 跳过整个数组的大小所以 arr1 相对于 arr 的差值是 40. 2.用指针遍历数组
既然可以把数组名当成地址存放到一个指针中我们使用指针来访问一个就成为可能。
#include stdio.h
int main()
{int arr[] {1,2,3,4,5,6,7,8,9,0};int *p arr; //指针存放数组首元素的地址int sz sizeof(arr)/sizeof(arr[0]);//数组元素个数for(int i 0; i sz; i){printf(arr[%d] %p p%d %p\n, i, arr[i], i, pi);}return 0;
} 可以看到我们可以通过指针遍历数组的每一个元素 pi 其实计算的是数组 arr 下标为i的地址。 那么 *(p1) 就可以访问数组 arr 的每一个元素。 三、指针数组、数组指针、函数指针
3.1指针数组
指针数组是存放指针的数组。
3.1.1指针数组的形式
我们先来看一下指针数组的样子其他类型同理
int* arr[5]; //数组名称arr 数组元素个数5 数组元素的类型int*
那么知道指针数组有什么用呢
3.1.2指针数组的使用案例
我们已经知道数组名在绝大多数情况下表示的是数组首元素的地址那么我们就可以用指针数组模拟出一个二维数组。
int arr1[] { 0,1,2,3,4,5 };
int arr2[] { 1,2,3,4,5,6 };
int arr3[] { 2,3,4,5,6,7 };int* arr[] { arr1,arr2,arr3 };
那我们应该怎么去使用这个模拟出来的二维数组呢 我们直接可以用它的下标进行访问。
区别
我们模拟出这个数组和真正二维数组的区别其实就是真实的二维数组每个元素的元素地址都是连续的而模拟出的二维数组它的每个一维数组地址并不是连续的。
3.2数组指针
数组指针是指向数组的指针。
int(*p)[10];/*解释p先和 * 结合说明p是一个指针变量然后指着指向的是一个大小为10个整型的数组。所以p是一个指针指向一个数组叫数组指针。*///这里要注意[]的优先级要高于*号的所以必须加上来保证p先和*结合。
我们知道整形、全精度浮点型等等都有一个数据类型int、double...... 当然在这里数组指针也有它的数据类型。 3.3函数指针
我们可以先来看一段代码
#include stdio.h
void test()
{printf(hello!\n);
}
int main()
{printf(%p\n, test);//打印test地址printf(%p\n, test);//打印test地址return 0;
} 从运行结果我们可以看出来函数名和数组名其实具有一样的效果但是为了便于观察以后在我们需要函数地址的时候我们还是会用 函数名 来实现。
如果我们想用指针存储上面的test函数我们应该怎么办呢
void(*pf)() test;pf1先和*结合说明pf1是指针指针指向的是一个函数指向的函数无参数返回值类型为void。 由上面我们可以得到
int max(int a, int b)
{if (a b)return a;elsereturn b;
}
int main()
{int (*pf2)(int, int) max;return 0;
} 这样我们就可以清楚的了解到函数指针的形式。
三、函数指针数组
3.1函数指针数组的形式 数组是一个存放相同类型数据的存储空间那我们已经学习了指针数组 比如 int * arr [ 10 ]; // 数组的每个元素是 int* 那要把函数的地址存到一个数组中那这个数组就叫函数指针数组那函数指针的数组如何定义呢 以上述 int max(int a, int b) 为例假设函数指针数组存放的都是此类函数 int( * parr[ 10])( int, int); parr先和 [ ] 结合表面parr是个数组。 数组的内容是什么呢 是 int (*)(int, int) 类型的函数指针。 3.2函数指针数组的用途转移表 我们以一个简单的计算器为例来看看使用函数指针数组的便捷。 准备内容 未使用函数指针数组时我们需要根据用户输入情况一个函数一个函数的调用 使用函数数组后我们只需要把准备阶段的四个函数全部封装到一个函数指针数组中 再接下来使用的时候我们就可以灵活运用 是不是简化了非常多
四、数组作为函数体参数
定义函数体时当参数为数组时既可以用数组接收也可以用指针接收其中用数组接收与数组的元素下标无关。 五、函数中用数组作为返回值
返回数组其实就是返回指针。
char* fun()
{char str[100] hello world!;return str;
}
int main()
{char* pf;pf fun();printf(%s\n, pf);return 0;
}
5.1返回静态局部数组的地址
上述代码有个明显缺陷
str 在 fun 函数体内创建为临时变量当我们在 main 函数中想用pf接收的时候 str 就已经被销毁了这时候我们就可以在 fun 函数内用 static 修饰我们的 str 来延长它的生命周期。
运行如图 5.2返回文字常量区的字符串的地址
常量字符串是个常量一直存在。 5.3返回堆内容的地址
malloc的头文件 #includestdlib.h malloc 为 str 动态申请内存大小为100单位是字节。 动态申请的内存在函数结束后也不会被释放。 堆区内容一直存在直到 free 才释放。
5.4总结 返回的地址地址指向的内存的内容得存在才有意义。