数组,指针容易忽略的问题

本文深入探讨C语言中的数组、指针及其与整型变量的运算,解析strlen、sizeof的行为,函数链接属性,动态空间申请与释放,以及输入处理和连续赋值问题。适合所有水平的程序员阅读。

tips:
    如果你觉得数组,指针方面的知识已经很扎实了,我建议你往下接着看,因为你有可能发现原来这些知识点被自己忽略了、、、
    如果你觉得数组,指针方面的知识不太扎实,那就更建议你看一下了,毕竟别人踩得坑,提前察觉也挺好的、、、

以图片为例子:

1.strlen的结束标志是 \0,sizeof的大小是静态分配时候数组的大小,因此,不会因为遇到 \0 就停止。
在这里插入图片描述


2 . 首先:数据类型的作用就是对待一块内存空间是怎么看的,如果以不同的视角看同一块空间中的内容,得出来的结果就是还不一样的。 比较的两个数的时候,也是比较的是内存空间中的内容。由此就出现了以下不同类型的a,b的值确实相同的现象。在这里插入图片描述


3.这里涉及到一个知识点,函数的链接属性(应该是这个叫法),就是函数的返回值不用新的变量接收,函数本身就是有值。在打印的时候再一次调用fun1(),导致结果是11。 另外,有不太清楚static用法的可以翻看博主关于static的介绍。


  1. 这里涉及到的知识点就是动态空间申请,释放malloc和free相关知识点了,malloc申请空间成功后,会返回申请空间的首地址,而free是对申请的空间进行释放,free释放空间时,指针必须指向申请的空间的起始位置!!!否则会释放错误,抛出异常。 因此常常做法是申请出来的空间返回值,用另一个指针变量操作,这也是一种良好的编程习惯。在这里插入图片描述

5.通过输入设备(键盘),将输入的值先保存在缓冲区中,在从缓冲区中取出一定大小的数据,通过输出设备(显示器)显示到屏幕上。输入了1234567890,但是实际上只从刚才的10个数据中取了5个数放到申请出来的input数组中,input数组中的内容是12345000,而 %s,遇到\0 停止。strlen遇到 \0 也会停止。
注意: char input[],输入的是数字,但是从char类型看过去就是ASCII码值, ASCII码值为0,对应的就是 \0。
在这里插入图片描述
ASCII码值与 char 类型的值之间对应关系:在这里插入图片描述


6.为什么合在一起就是正确,分开写就报错了呢?
原因: 没有理解数组名单独出现时,表示的是数组首地址。
         257行,是申请了空间,空间中存放的是h,e,l,l,o字符
         259,260行,是申请了空间,b表示的就是申请空间的首地址,b表示一个地址,地址是固定的,怎么可以给地址赋值呢?!!!
如果这一道题有问题的话,想必指针,数组,与整形变量之间的运算,就是指针移动这块的知识点有些混乱,建议看看博主其他相关博客。在这里插入图片描述


7.连续赋值问题:解决这个问题的最好方法就是,站在编译器的角度,看看代码中遇到的变量是不是没定义就使用了。
在这里插入图片描述

数组指针本质上是一个指针变量,它指向一个数组数组指针是可以修改的,只要其指向的数组地址是有效的,就可以通过赋值改变其指向的地址。但需要注意,数组指针的修改必须遵循类型匹配规则,并且不能修改数组名本身的地址。 以下是对数组指针可修改性的分析: ### 1. 数组指针的本质是变量 数组指针是一个指针变量,其值是所指向数组的地址。由于它是变量,因此可以被重新赋值以指向不同的数组,前提是该数组的类型长度与指针声明的类型一致。例如: ```c int arr1[5] = {1, 2, 3, 4, 5}; int arr2[5] = {6, 7, 8, 9, 10}; int (*p)[5] = &arr1; // p 指向 arr1 p = &arr2; // p 现在指向 arr2 ``` 上述代码中,`p` 是一个指向长度为 5 的整型数组指针,它最初指向 `arr1`,随后被修改为指向 `arr2`。这表明数组指针是可以被修改的[^4]。 ### 2. 数组名是常量地址,不可修改 与数组指针不同的是,数组名(如 `arr1`)代表数组的首地址,它是一个常量指针(`int* const` 类型),不能被赋值或修改。例如,以下代码是非法的: ```c int arr[5]; arr++; // 错误:数组名是常量指针,不能自增 ``` 这是因为数组名在表达式中会自动退化为指向其首元素的指针,但它本身并不是一个指针变量,而是一个常量地址。因此,数组名不能被修改指向其他内存位置[^3]。 ### 3. 数组指针的修改需类型匹配 数组指针的修改必须满足类型长度的匹配要求。例如,一个声明为 `int (*p)[5]` 的数组指针不能指向一个长度为 3 的整型数组: ```c int arr[3] = {1, 2, 3}; int (*p)[5] = &arr; // 错误:类型不匹配(int[3] 与 int[5] 不同) ``` 这是因为数组指针的类型不仅包括元素类型(如 `int`),还包括数组的长度(如 `[5]`),两者必须完全一致才能正确进行指针算术解引用操作[^1]。 ### 4. 数组指针指针算术 数组指针支持指针算术,且其加减操作是以整个数组的大小为单位进行的。例如,对于 `int (*p)[5]`,`p + 1` 会使指针移动 `5 * sizeof(int)` 字节: ```c int arr[5][5] = {{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}}; int (*p)[5] = &arr[0]; // p 指向第一个子数组 p++; // p 现在指向 arr[1] ``` 上述代码中,`p++` 使指针跳过整个长度为 5 的数组,从而指向下一个子数组。这也说明数组指针是可以修改的,并且其修改方式与普通指针不同[^4]。 ### 5. 常见误区与排错指南 - **误区 1:混淆指针数组数组指针** 指针数组(如 `int* arr[5]`)是一个由指针组成的数组,而数组指针(如 `int (*p)[5]`)是一个指向数组指针。两者的声明方式使用方式不同,不能混淆。 - **误区 2:试图修改数组名** 数组名是常量地址,不能被修改。试图对数组名进行赋值或自增操作会导致编译错误。 - **误区 3:忽略类型匹配** 数组指针的修改必须满足类型长度的匹配要求,否则会导致未定义行为或编译错误。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值