简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!
优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀
优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀
人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.
1.前言
本篇目的:C语言之指针的指向和指针的内容总结
2.C语言指针介绍
-
C语言中的指针,可以说是其最具特色且最具挑战性的部分。指针在C语言中起着至关重要的作用,它允许我们直接访问内存地址,并对存储在那些地址中的数据进行操作。下面,我们将对C语言中的指针进行详细的介绍。
-
首先,我们需要明白指针是什么。在C语言中,指针是一个变量,其值为另一个变量的地址,即内存位置的直接地址。通过指针,我们可以直接访问和修改存储在特定内存地址中的数据,这使得我们能够进行诸如动态内存分配、函数参数传递等高级操作。
-
其次,使用指针可以带来许多便利。例如,在函数参数传递时,如果我们需要修改一个变量的值,可以通过指针传递该变量的地址,然后在函数内部通过这个地址来修改变量的值。这种方式可以避免复制大量的数据,提高程序的效率。此外,指针还可以用于实现数组、字符串、链表等数据结构,以及进行文件操作等。
-
然而,指针的使用也带来了一些风险。如果指针没有被正确初始化,或者指向了错误的内存地址,就可能导致程序崩溃或者数据损坏。因此,在使用指针时,我们需要格外小心,确保指针指向了正确的内存地址,并且在不再需要指针时及时释放其占用的内存。
-
此外,C语言中的指针还有许多高级用法,如指向函数的指针、指向指针的指针(即二级指针)等。这些高级用法使得C语言能够实现更为复杂和灵活的功能,但同时也增加了编程的难度和复杂性。
-
总的来说,C语言中的指针是一把双刃剑,既带来了强大的功能和便利,也带来了风险和挑战。只有深入理解和掌握指针的使用方法和注意事项,我们才能充分利用C语言的强大功能,编写出高效、稳定、安全的程序。
3.代码实例
需求:使用get函数将,"456"字符串返回。
<1>.v1.0 指针指向字符串常量
#include <stdio.h>
#include <cstdlib>
#include <string.h>void get(char *name) {name = "345";
}int main() {char data[64] = "123"; get(data);printf("data = %s\n", data); return 0;
}
- 结论:以上实现不能完成"456"字符串的需求。
- 原因:
- 在C/C++中,函数参数传递是按值传递的,这意味着函数接收到的参数实际上是原始数据的副本。当你在函数内部修改参数时,只会修改副本的值,而不会影响原始数据。
- 在 get 函数中,name = “345”; 这行代码实际上只是
将指针 name 指向了字符串常量 "345" 的地址
,而不是修改了原始数据
。 - 我们来打印一下指针本身的地址和指向的地址验证下。
#include <stdio.h>
#include <cstdlib>
#include <string.h>void get(char *name) {printf("xxx--------------->line = %d, &name = %p, name = %p\n",__LINE__,&name,name);name = "345";printf("xxx--------------->line = %d, &name = %p, name = %p\n",__LINE__,&name,name);
}int main() {char data[64] = "123";printf("xxx--------------->line = %d, &data = %p, data = %p\n",__LINE__,&data,data);get(data);printf("data = %s\n", data);return 0;
}
打印:
xxx--------------->line = 13, &data = 0x7ffc176d7870, data = 0x7ffc176d7870
xxx--------------->line = 6, &name = 0x7ffc176d7858, name = 0x7ffc176d7870
xxx--------------->line = 8, &name = 0x7ffc176d7858, name = 0x55f7443e903d
data = 123
结果:
在 name = “345"后,name指向的地址由0x7ffc176d7870改变为0x55f7443e903d,并没有改变原来name指向地址的0x7ffc176d7870内容,所以不能返回"345”,因为在get函数中,改变name指针的地址是局部的,随着get函数调用结束,也随之被释放内存。
<2>.v2.0 修改指针指向地址的内容
#include <stdio.h>
#include <cstdlib>
#include <string.h>void get(char *name) {printf("xxx--------------->line = %d, &name = %p, name = %p\n",__LINE__,&name,name);memcpy(name, "456", 3);printf("xxx--------------->line = %d, &name = %p, name = %p\n",__LINE__,&name,name);
}int main() {char data[64] = "123";printf("xxx--------------->line = %d, &data = %p, data = %p\n",__LINE__,&data,data);get(data);printf("data = %s\n", data);return 0;
}
- 结论:以上实现可以完成"456"字符串的需求。
memcpy(name, "456", 3);
- 这行代码使用 memcpy 函数将字符串 “456” 的前3个字符复制到 name 指针所指向的内存空间中。
- 通过这个操作,原始的字符串 “123” 被修改为了 “456”。
- 因为 name 指针指向了 data 数组的起始位置,所以这行代码会修改 data 数组的内容。
- 总的来说,name = “345”; 操作并不会修改原始数据,而 memcpy(name, “456”, 3); 操作会修改原始数据。
- 如果你想要修改原始数据,你应该直接使用 memcpy 函数或类似的函数来修改参数所指向的内存内容;而不是让指针指向新的地址。
打印:
xxx--------------->line = 13, &data = 0x7ffd2f00f040, data = 0x7ffd2f00f040
xxx--------------->line = 6, &name = 0x7ffd2f00f028, name = 0x7ffd2f00f040
xxx--------------->line = 8, &name = 0x7ffd2f00f028, name = 0x7ffd2f00f040
data = 456
结果:这次修改了指针name指向的内容,而并没有修改name的指向,从第6行和第8行,打印可以看出指向的地址是0x7ffd2f00f040,并且没有改变。
<3>.name本身的地址&name为何改变?
- 可能有读者发现了&data到&name传给get函数是,发现name本身的地址改变了,这是为什么呢?
- 虽然 name 指针指向的内容是 data 数组的起始地址,但name 指针本身(地址)在 get 函数中是一个局部变量,它在栈上分配,因此其地址可能不同于在 main 函数中传递给它的地址。
- 因此,&name 的值在 get 函数中可能会不同于 main 函数中传递给它的地址,这取决于编译器如何分配栈上的变量。
- 总的来说,&name 的值不影响函数的行为,因为 get 函数接收到了正确的 data 数组的起始地址,可以正确地访问和操作数组的内容。