当前位置: 首页 > news >正文

C/C++ 指针与内存操作详解——从一级指针到字符串转换函数的完整解析

C/C++ 指针与内存操作详解——从一级指针到字符串转换函数的完整解析

本文将带你系统理解 一级指针与二级指针的区别数组拷贝的注意事项字符串转整数函数实现 等 C/C++ 编程中常见且易混淆的知识点,并配合详细代码示例与常见坑点分析,让你从入门到掌握。


一级指针与二级指针的讲解

在 C/C++ 中,指针不仅能指向数据,还能指向另一个指针。这就产生了一级指针与二级指针的区别。

  • 一级指针
    例如 char* pt,它本身存储的是一个内存地址,该地址指向具体数据值。
    举例:

    char ch = 'A';
    char* pt = &ch; // pt 存放的是 ch 的地址
    
  • 二级指针
    例如 char** pt,它存储的地址指向的是另一个指针变量,而不是直接指向数据。
    举例:

    char ch = 'A';
    char* p1 = &ch; // p1 是一级指针
    char** p2 = &p1; // p2 是二级指针,指向 p1
    

示例:指向字符串数组的二级指针

假设有一个字符串数组:

char* STR[] = {"ABCD", "EFGH", "IJKL"};
  • STR 存放的其实是多个字符串的首地址(每个元素是 char*)。
  • 若用指针指向它,应使用二级指针:
char** pt = STR; // pt 是二级指针,指向字符串数组

否则会出现类型不匹配的编译错误。

常见错误写法

char* pt = STR; // 错误!类型不匹配

因为 STR 的类型是 char**,直接赋给 char* 会丢失一层地址信息。


数组拷贝的注意事项

假设题目要求:从数组 X 拷贝 50 个字节到数组 Y

错误做法

Y = X; // 错误!数组名是地址常量,不能直接赋值

正确做法

使用 memcpy 按字节拷贝:

memcpy(Y, X, 50); // 从 X 复制 50 个字节到 Y

注意点

  1. memcpy 第三个参数是 字节数,不是元素个数。
  2. 如果数组类型是 int(每个元素占 4 字节),拷贝 50 字节意味着会拷贝 12 个多一点的 int 元素,不是整 50 个元素。
  3. 要明确题目要求的是 “字节” 还是 “元素”

字符串转整数函数实现

需求:实现 ascii_to_int,将数字字符串转换为整数。

函数原型

int ascii_to_int(const char* string);

实现思路

  1. 遍历字符串中的每个字符。

  2. 检查是否为数字字符('0' ~ '9')。

  3. 若是数字,按十进制累加计算:

    value=value×10+(当前字符−′0′) value = value \times 10 + (当前字符 - '0') value=value×10+(当前字符0)

  4. 若遇到非数字字符,立即返回 0。

代码示例

int ascii_to_int(const char* string) {int value = 0;for (int i = 0; string[i] != '\0'; i++) {if (string[i] < '0' || string[i] > '9') {return 0; // 遇到非数字字符}value = value * 10 + (string[i] - '0');}return value;
}

测试用例

#include <iostream>
using namespace std;int main() {cout << ascii_to_int("123") << endl;      // 输出 123cout << ascii_to_int("12a34") << endl;    // 输出 0
}

其他要点与常见误区

  • 指针类型必须匹配
    char*char** 不是同一种类型,不能随意赋值。

  • memcpy 是按字节拷贝
    不会考虑类型大小,要自己计算总字节数。

  • 题目细节决定实现方式
    要分清“字节”与“元素”的概念,尤其在涉及 sizeof 时避免出错。


总结

本文从指针基础到内存拷贝,再到字符串处理,串联了 C/C++ 中几个极易出错的知识点:

  1. 一级指针与二级指针的内存关系
  2. 字符串数组指针的正确定义
  3. 数组拷贝的正确方法与细节
  4. 字符串转整数的完整实现
http://www.dtcms.com/a/331364.html

相关文章:

  • 拒绝“孤岛式”作战,全方位构筑隧道应急通信解决方案
  • Java 学习笔记(基础篇2)
  • 13、C 语言结构体尺寸知识点总结
  • LeetCode 刷题【41. 缺失的第一个正数】
  • 【力扣322】零钱兑换
  • 非容器方式安装Prometheus和Grafana,以及nginx配置访问Grafana
  • GraphRAG查询(Query)流程实现原理分析
  • NetLimiter:精准掌控网络流量,优化网络体验
  • 《中国人工智能安全承诺框架》发布
  • arthas火焰图怎么看
  • 搭建 Docker 私有仓库
  • 前端css学习笔记5:列表表格背景样式设置
  • 【Golang】Golang内存泄漏问题排查(二)
  • 服务器路由相关配置Linux和Windows
  • Android POS应用在android运行常见问题及解决方案
  • 当消息队列遇上AI:飞算JavaAI实现智能流量调度与故障自愈实践
  • 在 Windows 系统中解决 Git 推送时出现的 Permission denied (publickey) 错误,请按照以下详细步骤操作:
  • LE AUDIO---Common Audio Service
  • C#WPF实战出真汁02--登录界面设计
  • STM32学习笔记11-通信协议-串口基本发送与接收
  • 从轨道根数计算惯性系到轨道系旋转矩阵
  • 2020/12 JLPT听力原文 问题二 1番
  • [激光原理与应用-268]:理论 - 几何光学 - 人眼结构与颜色感知
  • Nacos 配置热更新:Spring Boot Bean 自动获取最新配置
  • 【21-倾斜数据集的误差指标】
  • 金融风控实战:从数据到模型的信用评分系统构建全解析
  • 使用马尔可夫链如何解码、预测股市模式
  • 西门子PLC通过稳联技术EtherCAT转Profinet网关连接baumuller伺服器的配置案例
  • ThreadPoolExecutor 最佳实践
  • 8月AI面试工具测评:破解规模化招聘难题