C++指针解读(6)-- 指针和字符串

news2025/1/20 2:02:16

1、字符串的基本概念

(1)字符串的存储

字符串是存放在字符数组中的。比如字符串“hello”,在内存中是这么存放的:

这里要注意,在字符串的最后会加上一个'\0',也被称为NUL字符,表示字符串的结束位。比如定义char str[] = "hello",则sizeof(str)的长度是6,不是5。

(2)字符串的访问

既然字符串是字符按数组的方式存储的,我们可以用访问一维数组的方式来访问字符串。

char str[] = "hello";
printf(" %c\n", str[1]);

char* ch = &str[1];
printf(" %c\n", *ch);

(3)字符串常量池

用char数组str[]的方式定义字符串,我们也可以用下面的方式定义一个字符串:

char *str = "hello";

这里的str其实是一个char*型的指针变量,它指向字符串"hello"的首地址。

这种方式定义字符串时,"hello"是字符串常量,这个常量就放在字符串常量池中。

我们可以用代码来验证下:

const char* pstr1 = "hello";
const char* pstr2 = "hello";
printf(" p1 = %p, p2 = %p\n", pstr1, pstr2);

运行后发现pstr1, pstr2这2个地址是相同的,且每次运行地址都一样。这说明这个字符串常量是编译时就确定好的。

(4)sizeof()和strlen()

sizeof是C语言中的一个单目运算符,用来计算数据类型所占空间的大小,单位为字节;而strlen是一个函数,用来计算字符串长度(不包括字符串结束位NUL)。

char str1[] = "hello";
char str2[10] = "hello";
printf(" sizeof(str1) = %d, strlen(str1) = %d\n", sizeof(str1), strlen(str1));
printf(" sizeof(str2) = %d, strlen(str2) = %d\n", sizeof(str2), strlen(str2));

2、定义字符串的几种方式

(1)char str[] = {'h', 'e', 'l', 'l', 'o', '\0'};

定义了一个字符数组,长度为6,数组里的元素分布如下:{'h', 'e', 'l', 'l', 'o', '\0'}。

假如末尾没有NUL字符:char str[] = {'h', 'e', 'l', 'l', 'o' };

printf()输出str的值会是什么呢?sizeof()和strlen()的值分别是什么呢?

char str1[] = { 'h', 'e', 'l', 'l', 'o' };
printf(" %s\n", str1);
printf(" sizeof(str1) = %d, strlen(str1) = %d\n", sizeof(str1), strlen(str1));

这时,输出的str1是hello+一些乱码;sizeof(str1)是5,而strlen(str1)的值是个变数,每次的输出不一定相同。

因为字符串是以NUL作为字符串结束位的,现在缺少这个结束位,程序就没有办法做出正确的处理了。

(2)char str[] = "hello";

定义了一个字符数组,长度为6,系统会在末尾自动加上字位结束符NUL。

(3)char *pstr = "hello";

定义了一个字符指针变量,指向常量池中的字符常量"hello"。

4、字符指针变量和字符数组的比较

char *str1定义的是一个字符指针变量;char str2[10]定义的是一个字符数组,数组名代表数组元素首地址。

这是两个不同的概念,主要有以下区别:

(1)字符指针变量存放的是地址,指向字符串的第一个元素;字符数组就是一个存放字符的数组,一个元素就是一个字符。

(2)字符指针变量的值是可以改变的,但字符数组名的值不能改变(它只代表数组的首地址)。

const char *str1 = "hello";
printf(" %c\n", *str1);

str1++; //可以更改
printf(" %c\n", *str1);
    
char str2[10] = "hello";
str2++; //报错

(3)字符指针指向的字符串的内容不能被更改,但字符数组中各元素的值可以被更改。

const char *str1 = "hello";
str1[2] = 'a'; //报错

char str2[10] = "hello";
str2[2] = 'a'; //可以

(4)我们可以用str2[1], *(str2 + 1)这样的方式访问数组元素;对于字符指针变量,同样也可以用str1[1], *(str1 + 1)这样的方式访问。

const char *str1 = "hello";
printf(" %c, %c \n", str1[1], *(str1 + 1));

char str2[10] = "hello";
printf(" %c, %c \n", str2[1], *(str2 + 1));

(5)初始化的含义

char *str1 = "hello";

等价于:

char *str1;
str1 = "hello"; //把字符串的首地址给str

但字符数组的初始化:

char str2[10] = "hello";

不等价于:

char str2[10];
str2 = "hello"; //报错

其实这里的str1是个char *类型的指针变量,即字符指针变量,把字符数组的首地址赋给这个指针变量是没问题的。

而str2是数组的名字,代表字符数组首元素的地址,我们可以给这个地址赋值,但不能让地址去指向另外一个地址。

char str1[10];
*str1 = 'h'; //可以给地址赋值
strcpy(str1, "hello"); //可以直接内存拷贝

5、字符指针作函数参数

前面我们知道可以用两种方式来定义字符串,一种是字符数组,另一种是字符串指针变量。当函数的形参是字符串时,我们可以传字符数组的首地址,也可以传字符串指针变量。

(1)传字符数组的首地址

void print_str(char str[]) {
    int i = 0;
    while (str[i] != '\0') {
        printf("%c", str[i]);
        i++;
    }
}

int main()
{
    const char *str1 = "hello";
    print_str((char*)str1);

    char str2[10] = "hello";
    print_str(str2);

    return 0;
}

(2)传字符串指针变量

void print_str(char* str) {
    int i = 0;
    while (str[i] != '\0') {
        printf("%c", str[i]);
        i++;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1095570.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【算法训练-排序算法 三】【排序应用】合并区间

废话不多说,喊一句号子鼓励自己:程序员永不失业,程序员走向架构!本篇Blog的主题是【合并区间】,使用【数组】这个基本的数据结构来实现,这个高频题的站点是:CodeTop,筛选条件为&…

闪电藤文件传输助手上线

官网 临时官网:https://lightningvine.zishu.life/ 正式官网(备案中):lightningvine.cn 简介 闪电藤是基于LocalSend二次开发的一款局域网文件传输工具,完全兼容LocalSend,在它的基础上进行UI交互的重新设计…

前端取消请求

取消请求 发送一个异步请求获取数据,并在控制台中打印出返回结果。这里使用了 fetch 方法来发送请求,同时使用 AbortController 对象来实现请求的取消操作。 具体来说,代码中定义了一个 list 函数,该函数会创建一个 AbortContro…

在 VSCode 中使用 PlantUML

最近,因为工作需要绘制一些逻辑图,我自己现在使用的是 PlantUML 或者 mermaid,相比之下前者更加强大。不过它的环境也麻烦一些,mermaid 在一些软件上已经内置了。但是 PlantUML 一般需要自己本地安装或者使用远程服务器&#xff0…

计算机毕业设计-开题报告答辩常见问题!Javaweb项目答辩

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点…

2023年厦门市高等职业院校技能竞赛软件测试竞赛规程

2023年厦门市高等职业院校技能竞赛 软件测试竞赛规程 一、赛项名称 赛项名称:软件测试 竞赛形式:团体赛 赛项专业大类:电子信息 二、竞赛目的 (一)检验教学成效 本赛项竞赛内容以《国家职业教育改革实施方案》为设计方…

Java Swing医院就诊预约系统

一、系统概述 本系统是一款使用Java Swing开发的医院就诊预约系统,面向医院的医务人员和患者使用。 系统功能: 患者管理:添加/编辑/查询/删除患者信息 医生管理:添加/编辑/查询/删除医生信息 科室管理:添加/编辑/查询/删除科室信息 预约登记:患者选择医生和日期进行预约 预约…

【文档智能】多模态预训练模型及相关数据集汇总

前言 大模型时代,在现实场景中或者企业私域数据中,大多数数据都以文档的形式存在,如何更好的解析获取文档数据显得尤为重要。文档智能也从以前的目标检测(版面分析)阶段转向多模态预训练阶段,本文将介绍目…

分享项目管理软件排行榜!

无论是大型企业还是小型团队,项目管理是企业不可或缺的一部分。一个好的项目管理软件可以帮助企业有效地规划和实施项目,对于团队成员来说,也可以更好地分配任务、查看进度和提高团队合作能力。面对众多的项目管理软件,如何选择适…

JMM模型与并发三大特性

如何学: 分理解并发的三大特性,JMM工作内存和主内存关系,知道多线程之间如何通信的,掌握volatile能保证可见性和有序性,CAS就可以了 并发和并行 目标都是最大化CPU的使用率 并行(parallel):指在同一时刻&a…

Arcgis对图像重采样、打开查看运行结果的窗口、逐像元提取数值

1、Arcgis对图像重采样 然后打开数据管理工具-栅格-栅格处理-重采样 打开后,此处我们输入数据用导入的影像,X和Y代表重采样的大小为8*8 注意:输出文件需要有文件后缀,否则报错。 采样后,像元就变成了8*8一个像元。 2…

安装gymnasium[box2d]的问题

安装时总会报错 Building wheels for collected packages: box2d-pyBuilding wheel for box2d-py (setup.py) ... errorerror: subprocess-exited-with-error python setup.py bdist_wheel did not run successfully.│ exit code: 1╰─> [16 lines of output]Using setup…

gitlab自编译 源码下载

网上都是怎么用 gitlab,但是实际开发中有需要针对 gitlab 进行二次编译自定义实现功能的想法。 搜索了网上的资料以及在官网的查找,查到了如下 gitlab 使用 ruby 开发。 gitlab 下载包 gitlab/gitlab-ce - Packages packages.gitlab.com gitlab/gitl…

leetcode做题笔记174. 地下城游戏

恶魔们抓住了公主并将她关在了地下城 dungeon 的 右下角 。地下城是由 m x n 个房间组成的二维网格。我们英勇的骑士最初被安置在 左上角 的房间里,他必须穿过地下城并通过对抗恶魔来拯救公主。 骑士的初始健康点数为一个正整数。如果他的健康点数在某一时刻降至 0…

21GA-ELM,遗传算法优化ELM预测,并和优化前后以及真实数值进行对比,确定结果,基于MATLAB平台,程序已经调通,可以直接运行,需要直接拍下。

GA-ELM,遗传算法优化ELM预测,并和优化前后以及真实数值进行对比,确定结果,基于MATLAB平台,程序已经调通,可以直接运行,需要直接拍下。 21matlab时间序列预测极限学习遗传优化算 (xiaohongshu.co…

2023年(2024届)双非保研历程(中南、东南、浙大、信工所、国防科大、北邮)

个人情况 学校层次:双非 专业:信息安全(投的基本都是网安) 排名:2/66 英语:六级565,四级560 竞赛:大英赛国三、美赛H、蓝桥杯省一、数竞省一、词达人省一、数模国赛省三。 论文&…

【LeetCode刷题(数据结构与算法)】:二叉树之左叶子之和

给定二叉树的根节点 root ,返回所有左叶子之和 输入: root [3,9,20,null,null,15,7] 输出: 24 解释: 在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回 24 示例 2: 输入: root [1] 输出: 0 这都题目用递归的方法就可以解决…

牛客周赛 Round 15

A、 题目描述 游游拿到了一个正整数,她希望将它切割成两部分,使得它们的和为偶数。游游想知道有多少种合法的切割方案? 注:切割后的正整数允许出现前导零。 输入描述: 一个正整数,大小不超过10^100000 输出描述: 一个整…

参数解析(牛客)

目录 一、题目 二、代码 一、题目 二、代码 #include <iostream> #include <vector> using namespace std;int main() {string s;getline(cin, s);int i 0;vector<string>ret;while (i < s.size()){if (s[i] )//遇到空格直接跳过{i;}else if (s[i] …

[部署网站]01安装宝塔面板搭建WordPress

宝塔面板安装WordPress&#xff08;超详细&#xff09;_Wordpress主题网 参考教程 宝塔面板 - 简单好用的Linux/Windows服务器运维管理面板 官网 1.首先你需要一个服务器或者主机 &#xff08;Windows系统或者Linux系统都可以&#xff09; 推荐Linux系统更稳定&#xff0c;…