C++快速入门 (五) 数组 和 字符串

本文详细介绍了C++中的数组,包括内存中对象的存储、声明、访问元素和指针运算,并强调了数组边界检查的重要性。此外,还探讨了字符与字符数组的区别,字符串的概念,以及指向字面值字符串常量的指针和std::string的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一. 数组

(1). 内存中对象的存储
C++环境下 向内存中存储对象 就像是 向弹夹里装子弹,压进去一个然后在压进去另一个,抓到哪个子弹装哪个,是无序的,而有时,我们需要有序的存储一组相同类型的对象,可以通过封装成某种结构体,也可以使用更简单(看上去是)的数组。

数组能实现有序的存储,是用了一个投机取巧的方法,就是将所有成员所需要的内存大小一起申请,然后一次“压”进内存
(2). 声明数组
因为数组是一次申请所有元素占用内存大小的总和 ,所以在声明数组时,必须要确定其大小,要么说明数组有几个什么类型的元素,要么直接告诉数组要存储的元素是什么

int  array01[] = {1,2,3};
int  array02[3] = {};


(3). 访问数组元素
C++可以使用一种叫做下标(有些书上叫索引)的东西访问数组的元素,下标 以 0 表示数组的第一个元素,1表示第二个元素,n表示数组的第n个元素(如果它存在的话)

int array01[] = {10,20,30};
cout << array01[0];  //10
cout << array01[1];  //20
cout << array01[2];  //30


"猥琐"点的现在就会想,如果再向后读一个int长度(  array01[2+1] )会怎样?  好吧,它会非常老实的向后再读取一个int长度的内存并显示其值,有99.9的可能该内存区间保存的并不会是一个int,即便是int这个值对我们来说也毫无意义。 奇妙的是 即便这样超出索引调用其他对象的内容编译器也不会报错。

(4). 指针运算
数组名默认引用数组的第一个元素, 当使用下标引用元素时, 实际上它会按照如下的公式进行计算
  • 变量名(保存的首元素地址)+ 下标 * 元素类型长度  
即便我们使用下标获取 第一个元素 array[0] , 也会按照上边的公式计算(假设为 int 类型数组 / 32位处理器)
  • array首元素地址 + 0 * 4
这种直接操作内存地址 恰恰是指针所具备的功能, 实际上 在C++语言级,当使用下标引用元素时,可以将其看成是指针。

既然是指针,那假设有两个变量 a,b 可不可以在已知变量 a 的地址,和两个变量地址差值 ,通过运算让指针正确的指向 b ?,当然是可以的, 但这样做危险且实际意义不大

     int  a = 10,b = 10086;
      int  x = ((   int  )&a) - (( int  )&b);
      int  *p = &a;
      int  k = (x/4);
    cout <<   "变量 | b="  << b <<   " , 变量地址:"  << &b << endl;
    cout <<   "指针 | b="  << *(p-k)  <<   " , 指针指向:"  << (p-k) << endl;

虽然在语言级,下标具有指针的特性,但本质上两个是不同的东西, 这点 一定要明确。

(5). 数组的边界检查
很遗憾, 数组本身不提供边界检测,甚至不能查询数组中的元素个数,所以要遍历数组时, 需要声明常量来保存数组元素个数

     const   int  array_size = 3;
      int  array01[array_size] = {11,22,33};
      for  ( int  i =0; i < array_size; i++)
    {
        cout << array01[i] << endl;
    }


或许你已经想到了另一种获取数组元素个数的方法,对咧~ 就是 "先称了一个,又称了一堆,做了个除法~"

const   int  array_size =   sizeof(array01)/   sizeof  (  int );


[sizeof()用于过去类型大小]

二. 字符串

(1). 字符 和 字符数组
当我们输入并显示字符, 计算机做了如下工作:
  • 查看我们输入的数字(没错是数字),再根据输入的数字在"字典中"找到并显示对应的某个字符的矢量图
[ 要进一步了解计算机如何显示文字,可以读这篇文章,顺便告诉我美人鱼你选A还是B ] 

充当"字典"的最早叫 ASCII码表, ASCII的映射条目数只有127个。由于映射条目数太少, 很多语言肯定表示不了(如中文),于是就出现了 Unicode。


根据 Unicode 陆续出了很多版本的编码 如 UTF-8(变长), UTF-16 , UTF-32,可以映射的条目越来越多,对应的 每个字符占用的空间越大,
UTF-8是变长编码,既字符可以占一个字节,也可以是两个或三个字节。利于网络传输,因为它不会像定长编码( 如 UTF-16 每个字符固定占两个字节 ),一旦传输中丢了一个字节数据,后边的文字都会悲剧(乱码)。

C++ 中用 char(一个字节)表示 ,用 wchar_t(两个字节) 来表示 Unicode(一般为UTF-16)。 

[Java中 char 是两个字节,Linux下wchar_t是四个字节,对应utf-32 ]
(2). 字符串
由于字符串都是变长的(天知道你要写多少个字),所以 C/C++ 用一个特殊的字符“\0”来标识字符串结束位。
(3). 字符数组
字符数组就是其元素为表示字符类型的数组,这个没什么好说的,只是注意一点。当使用 字面值字符串常量 来初始化字符串时,末尾会有 字符串结束标记“\0” 

     char  array01[] =   "hello"  ;
      const   int  array_size =   sizeof  (array01)/ sizeof  (  char);
    cout << array_size << endl;   // 6

(4). 指向 字面值字符串常量 的指针
当如下声明一个指针时,

char   *p =  "hello" ;

直接编译会报错,编译器非要你将指针设置为常量指针才罢休。其实 当 指针指向  字面值字符串常量时,而该字符串会存储在 运行环境中一个叫 只读存储区 的内存空间里,该区域的内容均不能修改。所以 *p也就变成了前边说过的 指向常量的非常量指针

char   const  *p =   "hello";

(5). string
C++中,将 传统的字符串封装成了一个新的类型 string,该类型提供了很多函数可以很方便的操作字符串,具体可以 看这里

[ Java,C# 中直接 string设置为内置类型,其在语言级就是字符串,并且是不可变的  ]


-

<原创文章 转载请注明出处 http://blog.youkuaiyun.com/meiwm 谢谢>


作者:meiwm
出处: http://blog.youkuaiyun.com/meiwm
本文为原创,本文版权归作者所有。欢迎转载,但请务必保留此段声明,且在文章页面明显位置给出原文连接,谢谢合作。

-

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值