C++ 基础与深度分析 Chapter3 数组(数组的引入、指针、其他字符、C的字符串、多维数组)


在这里插入图片描述

数组的引入

在这里插入图片描述

#include <iostream>
#include <type_traits>

int main()
{
    int a; // int 
    int b[10]; // int[10]
    std::cout << std::is_same_v<decltype(b), int[10]> << std::endl; // 1
}

在这里插入图片描述

#include <iostream>
#include <type_traits>

int b[3]; // 3个值在全局域默认初始化为0
int main()
{
    int a[3] = {1, 2, 3}; // 聚合初始化
    int b[3];  // 3个值在函数内部默认初始化为随机数
    int c[3] = {1, 2}; // c = {1, 2, 0}
    int d[3] = {}; // d = {0, 0, 0}

}
int main()
{
    int b[] = {1, 2, 3}; // 编译器自动推导出中括号里的值为3
    int a[3] = {1, 2, 3, 4} // 报错,中括号数值要么不写,要么大于等于{}个数
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
数组为什么不能复制,因为cpp关注性能的,数组的复制非常耗时间的,时间和数组长度相关。来一个数组,需要开辟一大块内存。

int main()
{
    char str1[] = "Hello"; // char[6],最后有一个\0,表示字符串的结束
    char str2[] = {'H', 'e', 'l' ,'l', 'o'}; // char[5]
}

在这里插入图片描述

int main()
{
    int* a[3]; // a中3个元素都是指针
    int x1 = 1;
    int x2 = 2;
    int x3 = 3;
    int* x[3] = {&x1, &x2, &x3}; // 将x1, x2, x3地址放入指针数组
}

在这里插入图片描述

int main()
{
    int b[3];
    int (&a)[3] = b; // a是一个数组b的引用
    int (*c)[3] = &b; // c是一个数组b的指针
}
int main()
{
    int x1;
    int x2;
    int x3;
    int& a = {x1, x2, x3}; //cpp没有引用的数组,也就是不能里面元素都是引用
}

为什么不能定义引用的数组,引用表示对象的别名,数组里面的元素一定要是对象,所以不能声明引用的数组。

int main()
{
    int a[3] = {1, 2, 3};
    std::cout << a[0] << a[1] << a[2] << std::endl;
}

在这里插入图片描述
在这里插入图片描述

int main()
{
    int a[3] = {1, 2, 3};
    auto b = a; // b是一个指向数组a第一个元素的指针
    std::cout << *b << std::endl; // 1
    std::cout << b << std::endl; // 0x7ffee7fd76dc
    std::cout << a << std::endl; // 0x7ffee7fd76dc
    std::cout << &(a[0]) << std::endl; // 0x7ffee7fd76dc
    std::cout << &(a[1]) << std::endl; // 0x7ffee8a106e0
}

中括号不是数组特有的,指针也可以使用:

int main()
{
    int a = 3;
    int* ptr = &a;
    std::cout << *ptr << std::endl; // 3
    std::cout << ptr[0] << std::endl; // 3
}

x[y] 会被编译器解析成&(x + y)

在这里插入图片描述
在这里插入图片描述
超出界限,是非常危险的事,不要越界。
在这里插入图片描述

数组的指针

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
b是引用,就可以包含数组个数3的信息。

类型是在编译中用到的,所以在编译完后,系统文件链接时,类型信息就没有了。我们不知道是数组还是指针,只是知道他们是同名,这时候运行的时候才会报错。
在这里插入图片描述
上述的数组声明是可以的。Unknown Bounded Array,不关心数组中元素个数。
在这里插入图片描述

#include <iostream>
#include <type_traits>
#include <typeinfo>
using namespace std;


int main()
{
    int a[3] = {1, 2, 3};
    &(a[0]); // 获取数组开头的指针
    a; // 获取数组开头的指针
    begin(a); // 获取数组开头的指针


    &(a[3]); // 获取数组结尾后一个元素的指针
    a + 3; // 获取数组结尾后一个元素的指针
    end(a); // 获取数组结尾后一个元素的指针

    
    cout << &(a[0]) << endl;
    cout << &(a[3]) << endl;
    cout << std::begin(a) << endl;
    cout << std::end(a) << endl;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include <iostream>
#include <type_traits>
#include <typeinfo>
using namespace std;


int main()
{
    int a[3] = {1, 2, 3};
    auto ptr1 = a;
    auto ptr2 = a + 2; // 数组增加
    cout << (ptr1 == ptr2) << endl; // 数组比较
    cout << (ptr2 - ptr1) << endl; // 数组距离
    cout << *ptr2 << endl; // ptr解引用
    cout << ptr2[0] << endl; // ptr索引
}

其他操作

在这里插入图片描述
sizeof c语言比较常用的

int main()
{
    int a[3];
    cout << sizeof(a) << endl; // 12
    cout << sizeof(int) << endl; // 4
    cout << sizeof(a) / sizeof(int) << endl; // 3 利用这样的方法求数组a的长度
}

std::size是cpp的库方法。

int main()
{
    int a[3];
    cout << std::size(a) << endl; // 3
}

因为cpp设定end是数组后一位,所以end-begin就是数组长度。

int main()
{
    int a[3];
    cout << std::end(a) - std::begin(a) << endl; // 3
}
int main()
{
    int a[3];
    cout << std::cend(a) - std::cbegin(a) << endl; // 3
}

在这里插入图片描述
在这里插入图片描述
所以cbegin和cend不作为计算数组长度推荐的方法。
sizeof是c语言的,而且写起来不方便,也不做推荐。
推荐:std::size(a);

int main()
{
    int a[4] = {2, 3, 5, 8};
    size_t index = 0;
    while (index < std::size(a))
    {
        cout << a[index] << endl;
        index += 1;
    }
}

用指针遍历

int main()
{
    int a[4] = {2, 3, 5, 8};
    auto ptr = std::cbegin(a);
    while (ptr != std::cend(a))
    {
        cout << *ptr << endl;
        ptr += 1;
    }
}

下面是for循环遍历

int main()
{
    int a[4] = {2, 3, 5, 8};
    for (int x : a)
    {
        cout << x << endl;
    }
}

在这里插入图片描述

C的字符串

在这里插入图片描述

int main()
{
    char str[] = "Hello"; // null-terminated string
    auto ptr = str; // ptr 是一个char*,指向第一个字符
    cout << strlen(str) << endl; // 5
    cout << strlen(ptr) << endl; // 5
}
int main()
{
    char str[5] = {'H', 'e', 'l', 'l', 'o'}; // char[5]
    auto ptr = str; // ptr 是一个char*,指向第一个字符
    cout << strlen(str) << endl; // 11 strlen方法会找到 \0 才会停止,所以不能用这个方法
    cout << strlen(ptr) << endl; // 11 strlen方法会找到 \0 才会停止,所以不能用这个方法
}
int main()
{
    char str[] = {'H', 'e', 'l', 'l', 'o', '\0'}; // char[5]
    auto ptr = str; // ptr 是一个char*,指向第一个字符
    cout << strlen(str) << endl; // 5 strlen方法会找到 \0 才会停止,需要手动加\0
    cout << strlen(ptr) << endl; // 5 strlen方法会找到 \0 才会停止,需要手动加\0
}

通常来说,字符串数组,都需要\0这个结束符。

多维数组

在这里插入图片描述

int main()
{
    int a[3][4]; // 多维数组
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
x[0] = 1, 2, 3 ; x[1] = 4, 0, 0;这种写法不推荐

只能省略最高位,但是不建议省略。

int main()
{
    int x[3][4]; // 缺省初始化
    int b[3][4] = {1, 2, 3, 4, 5};
    // (int int int int), (int int int int), (int int int int)
    // 1 2 3 4 5 0 0 0 0 0 0 0
    int c[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}};
    // 1 2 3 4, 5, 6, 7, 8, 0, 0, 0, 0
    cout << c[1] << endl;
}

在这里插入图片描述
在这里插入图片描述

int main()
{
    int x[2][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}};
    for (auto& p : x)
    {
        for (auto q : p)
        {
            cout << q << endl;
        }
    }
}

在这里插入图片描述


int main()
{
    int x[2][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}};
    size_t index0 = 0;
    while (index0 < 2)
    {
        size_t index1 = 0;
        while (index1 < 4)
        {
            cout << x[index0][index1] << endl;
            index1 += 1;
        }
        index0 += 1;
    }
}

int main()
{
    int x[2][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}};
    size_t index0 = 0;
    while (index0 < std::size(x))
    {
        size_t index1 = 0;
        while (index1 < std::size(x[index0]))
        {
            cout << x[index0][index1] << endl;
            index1 += 1;
        }
        index0 += 1;
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
指针的遍历多维数组。


int main()
{
    int x[2][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}};
    auto ptr1 = std::begin(x);
    while (ptr1 != std::end(x))
    {
        auto ptr2 = std::begin(*ptr1);
        while (ptr2 != std::end(*ptr1))
        {
            cout << *ptr2 << endl;
            ptr2 += 1;
        }
        ptr1 += 1;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值