C语言之指针的指向地址和指针的内容总结(八十九)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!

优质专栏:Audio工程师进阶系列原创干货持续更新中……】🚀
优质专栏:多媒体系统工程师系列原创干货持续更新中……】🚀
优质视频课程:AAOS车载系统+AOSP14系统攻城狮入门实战课原创干货持续更新中……】🚀

人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.

更多原创,欢迎关注:Android系统攻城狮

欢迎关注Android系统攻城狮

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 数组的起始地址,可以正确地访问和操作数组的内容。

相关推荐

  1. C++指针指向字符串首地址例子

    2024-04-07 19:32:01       23 阅读
  2. C语言指针函数函数指针

    2024-04-07 19:32:01       19 阅读
  3. C语言指针数组 指针运算

    2024-04-07 19:32:01       71 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-07 19:32:01       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-07 19:32:01       100 阅读
  3. 在Django里面运行非项目文件

    2024-04-07 19:32:01       82 阅读
  4. Python语言-面向对象

    2024-04-07 19:32:01       91 阅读

热门阅读

  1. 移动端h5 js手势封装

    2024-04-07 19:32:01       40 阅读
  2. C# 索引器的范例和要点

    2024-04-07 19:32:01       47 阅读
  3. leetcode热题100.数组中的第k大的元素

    2024-04-07 19:32:01       38 阅读
  4. [leetcode] 66. 加一

    2024-04-07 19:32:01       34 阅读
  5. GPU的了解

    2024-04-07 19:32:01       46 阅读
  6. Redis实现网站访问人数统计

    2024-04-07 19:32:01       42 阅读
  7. 设计模式:观察者模式

    2024-04-07 19:32:01       42 阅读
  8. 全量知识系统 设计和实现的切入点探讨 (Q&A)

    2024-04-07 19:32:01       36 阅读
  9. 数据库面试题之Mysql

    2024-04-07 19:32:01       37 阅读