1.1 指向数组首元素的指针

程序结构图:

p[i] 等价于 *(p+i),操作都是指针所指向的内存。
1.2 指针的加减运算
加法:

减法:

1.3 指针数组

关于计算指针数组元素个数的解释:

程序结构图:

1.4 形参中的数组
结论:

举例:

此处的a = NULL不会报错,因为传进来的a是一个指针变量,可以被赋值。
对于如下使用情况:

a = NULL会报错,因为a是一个常量,它是数组首元素的地址- 这种传递参数的形式也不能达到效果
所以我们需要把数组元素个数也传递进去:

至于为什么形参中的数组不是数组,因为可能我们定义的数组很大,元素个数不确定,拷贝到形参里的话是很麻烦的,同时指针效率比较高也体现在这,所以这里形参只存首元素的地址就行。
结构图如下:

1.5 返回局部变量的地址

结构图如下:

运行到第27行的时候程序会报错,因为调用函数结束后,操作系统分配的内存会释放掉,调用函数里的变量是局部变量也会被释放掉,此时p存储的是一个野指针,对野指针操作会报错。
甚至在Linux 64位gcc环境下,不允许返回局部变量的地址,,如下图:

1.6 返回全局变量的地址
- 在{ }外面定义的变量,就是全局变量,全局变量任何地方都能使用
- 全局变量只有在程序运行结束后,才释放


1.7 字符串打印说明
为什么%s会直接打出字符串:

字符串很特别,它没有操作 *号,但是它已经操作了这个指针指向的内存,因为%s的内部含有如下处理:

但是如果想用指针操作字符串名时:

也可以进行如下操作:

1.8 字符指针

结构图1:

结构图2:

1.9 字符串拷贝问题
错误的拷贝示例:

正确的拷贝:

结构图如下:

补充记忆知识点:熟记


1.10 字符串常量

- 每定义一个字符串都有一个地址,这个地址就是字符串首元素的地址,只要字符串的内容一样,它们的地址就是一样的,如上图
fun()函数的输出结果和第二个printf()对应的输出地址结果相同:

printf("s3 = %s\n","hello mike"+1)
表示字符串首元素地址加一,指到下一个地址了。
输出结果:s3 = ello mike
验证了字符串就是首元素的地址
所以如下程程序就是合理的,因为一个字符串本身就是一个地址,将它赋给指针变量是正确的:

输出结果三个地址是一样的:

结构图如下:

需要注意的情况,文字常量区不允许修改:
举例1:

结构图如下:

举例2:

结构图:

上图程序最后的函数调用结果依旧是错误的。
1.11 字符串常量初始化问题

结构图:

1.12 main形参使用说明
以下两种初始化方式结果相同,形式不同:

表示这个数组有三个元素,每个元素都是char * 类型,char * 类型保存了它的地址。
因为p[i]就是每个字符串的首元素地址,直接打印即可,打印每个元素的方式:

输出结果如下:

首先明确以下三种定义结果是一样的:

此时对应如下情况就是成立的,它的形参形式就和main里的一样,也就能理解main里的形参含义了:

所以对应于main函数里的参数,解释如下:

1.13 查找匹配字符串出现的次数

1.14 两头堵模型

还可以继续操作拷贝这个字符串:

本文深入探讨C语言中指针与数组的关系,包括指针的加减运算、数组元素计数、形参中数组的理解、返回局部及全局变量地址的注意事项、字符串处理技巧、字符串拷贝的正确方式,以及字符串常量的特性。通过实例解析,帮助读者掌握指针与数组的高级应用。
2021

被折叠的 条评论
为什么被折叠?



