高端 网站开发,wordpress加邮箱代码,虚拟空间官网,网页版设计指针 一.指针与数组的联系1.数组名的理解2.使用指针访问数组3.一维数组传参的本质 二.字符指针1.字符指针隐藏秘密2.常量字符串3.《剑指offer》笔试题 三.二级指针四.指针数组1.指针数组模拟二维数组 一.指针与数组的联系
1.数组名的理解 也许大部分人认为数组名就是一个名称没有什么特殊意义但是这么想的话你就错了其实数组名有着重要的意义——数组首元素的地址。 你若不信的话可以测试一下
#include stdio.h
int main()
{int arr[10] { 1,2,3,4,5,6,7,8,9,10 };printf(arr[0] %p\n, arr[0]);printf(arr %p\n, arr);return 0;
}我们发现数组名和数组首元素的地址打印出的结果⼀模⼀样数组名就是数组首元素(第⼀个元素)的地址。
#include stdio.h
int main()
{int arr[10] { 1,2,3,4,5,6,7,8,9,10 };printf(%d\n, sizeof(arr));return 0;
}思考既然数组名是数组首元素的地址那么输出的不应该是指针变量的大小4/8吗为什么输出的结果又是40呢
结论 其实数组名就是数组首元素(第⼀个元素)的地址是对的但是有两个例外 sizeof(数组名)sizeof中单独放数组名这⾥的数组名表示整个数组计算的是整个数组的大小单位是字节。 数组名这里的数组名表示整个数组取出的是整个数组的地址整个数组的地址和数组首元素的地址虽然数值一样但还是有区别的 除此之外任何地方使用数组名数组名都表示首元素的地址。 再度思考那么数组的地址数组名与数组首元素的地址这三种又存在什么关系呢以下的代码将使你清晰理解这三者的联系
#include stdio.h
int main()
{int arr[10] { 1,2,3,4,5,6,7,8,9,10 };printf(arr[0] %p\n, arr[0]);printf(arr[0]1 %p\n, arr[0] 1);printf(arr %p\n, arr);printf(arr1 %p\n, arr 1);printf(arr %p\n, arr);printf(arr1 %p\n, arr 1);return 0;
}数组的地址数组名与数组首元素的地址打印的结果都是相同的这是为什么呢
结论
arr[0]和arr[0]1相差4个字节arr和arr1相差4个字节是因为arr[0]和arr都是首元素的地址1就是跳过⼀个元素也就是4个字节而每个字节都有对应的地址且地址相差1所以它们的地址就相差4。arr和arr1相差40个字节这就是因为arr是数组的地址1操作是跳过整个数组就是40个字节地址相差0x26到这里大家应该搞清楚数组名的意义了吧。
2.使用指针访问数组 有了前面知识的支持再结合数组的特点我们就可以很方便的使用指针访问数组元素了如下代码
#include stdio.h
int main()
{int arr[10] { 1,2,3,4,5,6,7,8,9,10 };int i 0;int* p arr[0];//等价于int* p arr;for (i 0; i 10; i){printf(%d , *(p i));//等价于*(arr i)//等价于arr[i]p[i]}return 0;
}将*(pi)换成p[i]也是能够正常打印的所以本质上p[i]是等价于*(pi)。同理arr[i]应该等价于*(arri)数组元素的访问在编译器处理的时候也是转换成首元素的地址偏移量求出元素的地址然后解引用来访问的。还可以这么写*iarr以及这么写i[arr]是不是很奇妙啊了解一下就行了不推荐这么写。 思考为什么可以使用指针来访问数组呢 总结
数组在内存是一块连续的空间存放的是相同类型的元素。指针变量是一个变量是存放地址的变量数组和指针不是一回事但是可以利用指针来访问数组指针进行不断地1解引用可以很方便地遍历数组取出数组的内容。
3.一维数组传参的本质 首先从⼀个问题开始我们之前都是在函数外部计算数组的元素个数那我们可以把数组传给⼀个函数后函数内部求数组的元素个数吗如下
#include stdio.h
void test(int arr[])
{int sz2 sizeof(arr) / sizeof(arr[0]);printf(sz2 %d\n, sz2);
}
int main()
{int arr[10] { 1,2,3,4,5,6,7,8,9,10 };int sz1 sizeof(arr) / sizeof(arr[0]);printf(sz1 %d\n, sz1);test(arr);return 0;
}我们发现在函数内部是没有正确获得数组的元素个数这又是为什么呢你也许会想指针怎么这么…此处省略一万字要尝试先接受它以后学习多了自然都解释地清了。
这就要学习数组传参的本质了上个小节我们学习了数组名是数组首元素的地址那么在数组传参的时候传递的是数组名也就是说本质上数组传参传递的是数组首元素的地址。所以函数形参的部分理论上应该使用指针变量来接收首元素的地址。那么在函数内部我们写sizeof(arr) 计算的是⼀个地址的大小单位字节而不是数组的大小单位字节。正是因为函数的参数部分是本质是指针所以在函数内部是没办法求的数组元素个数的。那形参为什么可以写成数组的形式呢这是因为C语言考虑到了学者的感受在学习数组的时候如果一来就传地址形参用指针变量来接收学者会非常地疑惑的。所以说C语言并不是这么冷若冰霜的。
总结⼀维数组传参形参的部分可以写成数组的形式也可以写成指针的形式。
二.字符指针
1.字符指针隐藏秘密 在指针的类型中我们知道有⼀种指针类型为字符指针 char* 存放的是字符的地址比如
#includestdio.h
int main()
{char ch w;char* pc ch;*pc w;return 0;
}还有⼀种使用方式如下
#includestdio.h
int main()
{const char* pstr hello bit.;//这里是把一个字符串放到pstr指针变量里了吗?printf(%s\n, pstr);return 0;
}代码 const char* pstr “hello bit.”;特别容易让同学以为是把字符串 hello bit 放到字符指针 pstr 里了但是不妨考虑一下指针存放的是地址怎么可能会存放字符串呢其实本质是把常量字符串 hello bit. 首字符h的地址放到了指针变量pstr中。
2.常量字符串 常量字符串顾名思义该字符串不能被修改接下来看一个代码
#includestdio.h
int main()
{char arr[] abcdef;char* p1 arr;*p1 b;printf(%s\n, arr);char* p2 abcdef;*p2 b;printf(%s\n, p2);return 0;
}可以发现指针p1指向的空间可以修改而修改指针p2指向的空间则报错写入访问权限冲突。这是因为p2是常量字符串它还有更重要的特点接下来带我慢慢为你分析一二请看以下的笔试题。
3.《剑指offer》笔试题 《剑指offer》中收录了⼀道和字符串相关的笔试题我们⼀起来学习⼀下
#include stdio.h
int main()
{char str1[] hello bit.;char str2[] hello bit.;const char* str3 hello bit.;const char* str4 hello bit.;if (str1 str2)printf(str1 and str2 are same\n);elseprintf(str1 and str2 are not same\n);if (str3 str4)printf(str3 and str4 are same\n);elseprintf(str3 and str4 are not same\n);return 0;
}你做对了吗不管对错看了这张图就都明白了。 这里str3和str4指向的是⼀个同⼀个常量字符串。C/C会把常量字符串存储到单独的⼀个内存区域只读数据区当几个指针指向同⼀个字符串的时候他们实际会指向同⼀块内存。但是用相同的常量字符串去初始化不同的数组的时候就会开辟出不同的内存块。所以str1和str2不同str3和str4相同。
总结
str1和str2是两个数组数组的操作方式是将右边常量字符串的内容拷贝进来所以他们是两个空间只是内容相同所以str1 ! str2。而str3和str4是两个指针 编译器在处理的时候会将相同的常量字符串做成同一个地址所以str3和str4指向的是同一个常量字符串所以str3 str4。
三.二级指针 思考指针变量也是变量是变量就有地址那指针变量的地址存放在哪里这就是二级指针如下代码
#include stdio.h
int main()
{int a 10;int* pa a;int** ppa pa;*pa 20;printf(%d\n, a);//20**ppa 30;printf(%d\n, a);//30return 0;
}对于⼆级指针的运算有
*ppa 通过对ppa中的地址进行解引用这样找到的是 pa *ppa 其实访问的就是 pa。
int b 20;
*ppa b;//等价于 pa b; **ppa 先通过 *ppa 找到 pa ,然后对 pa 进行解引用操作 *pa 那找到的是 a。
**ppa 30;
//等价于*pa 30;
//等价于a 30; 四.指针数组 思考指针数组是指针还是数组
我们类比⼀下整型数组是存放整型的数组字符数组是存放字符的数组。那指针数组呢是存放指针的数组指针数组的每个元素都是用来存放地址指针的。指针数组的每个元素是地址又可以指向一块区域。
1.指针数组模拟二维数组
#include stdio.h
int main()
{int arr1[] { 1,2,3,4,5 };int arr2[] { 2,3,4,5,6 };int arr3[] { 3,4,5,6,7 };//数组名是数组首元素的地址类型是int*的就可以存放在parr数组中 int* parr[3] { arr1, arr2, arr3 };int i 0;int j 0;for (i 0; i 3; i){for (j 0; j 5; j){printf(%d , parr[i][j]);//等价于*(*(parri)j)}printf(\n);}
}parr是数组名表示首元素的地址也就是数组的地址这就牵扯到了数组指针数组指针又是什么呢 预知后续如何且听下回分解指针的奥秘三即将来袭你准备好了吗 创作不易如果能帮到你的话能赏个三连吗感谢了