指针和数组

对数组的元素使用取地址符就能得到指向该元素的指针:

    string nums[] = {"one","two","three"};//数组的元素是string对象
    string* p = &nums[0];//p指向nums的第一个元素

编译器自动讲数组名字替换为一个指向数组首元素的指针:

    string* p2 = nums;//等价于p2 = &nums[0]

当数组作为一个auto变量的初始值时,推断得到的类型是指针而非数组:

    int ia[] = {0,1,2,3,4,5,6,7,8,9};//ia是一个含有10个整数的数组
    auto ia2(ia);//ia2是一个整型指针,不能用int值给指针赋值
    ia2 = 42;//错误:ia2是一个指针,不能用int值给指针赋值

使用ia作为初始值执行初始化的过程:

    auto ia2(&ia[0]);//ia2的类型是int*

decltype(ia)返回的类型是由10个整数构成的数组:

    //ia3是一个含有10个整数的数组
    decltype(ia) ia3 = {0,1,2,3,4,5,6,7,8,9};
    ia3 = p;//错误:不能用整型指针给数组赋值
    ia3[4] = i;//正确:把i的值赋给ia3的一个元素

指针也是迭代器

允许使用递增运算符将指向数组元素的指针向前移动到下一个位置上:

    int arr[] = {0,1,2,3,4,5,6,7,8,9};
    int* p = arr;//p指向arr的第一个元素
    ++p;//p指向arr[1]

获取尾元素之后的那个不存在的元素的地址:

    int* e = &arr[10];//指向arr尾元素的下一位置的指针

尾后指针不指向任何元素,不能对尾后指针执行引用或递增的操作。

输出arr的全部元素:

    for (int *b = arr; b != e; ++b)
        cout << *b << endl;

标准库函数begin和end

将数组作为begin和end函数的参数:

    int ia[] = {0,1,2,3,4,5,6,7,8,9};//ia是一个含有10个整数的数组
    int *beg = begin(ia);//指向ia的首元素的指针
    int *last = end(ia);//指向arr尾元素的下一个位置的指针

begin函数返回指向ia首元素的指针,end函数返回指向ia尾元素下一位置的指针,这两个函数定义在iterator头文件中。

假设一个整型数组,找到arr中的第一个负数:

    //pbeg指向arr的首元素,pend指向arr尾元素的下一位置
    int* pbeg = begin(arr), * pend = end(arr);
    //寻找第一个负值元素,如果已经检查完全部元素则结束循环
    while (pbeg != pend && *pbeg >= 0)
        ++pbeg;

指针运算

给一个指针加上(减去)某整数值,结果仍是指针。新指针指向的元素与原来的指针相比前进了(后退了)该整数值个位置:

    constexpr size_t sz = 5;
    int arr[sz] = {1,2,3,4,5};
    int *ip = arr;//等价于int *ip=&arr[0]
    int* ip2 = ip + 4;//ip2指向arr的尾元素arr[4]

给指针加上一个整数,得到的新指针仍需指向同一数组的其他元素,或者指向同一数组的尾元素的下一位置:

    //正确:arr转换成指向它首元素的指针;p指向arr尾元素的下一位置
    int* p = arr + sz;//使用警告:不要解引用
    int* p2 = arr + 10;//错误:arr只有5个元素,p2的值未定义

和迭代器一样,两个指针相减的结果是它们之间的距离,参与运算的两个指针比必须指向同一个数组当中的元素:

auto n = end(arr) - begin(arr);//n的值是5,也就是arr中元素的数量

两个指针相减的结果的类型是ptrdiff_t的标准库类型,定义在cstddef头文件中的机器相关的类型,差值是一种带符号类型。

只要两个指针指向同一个数组的元素,或者指向该数组的尾元素的下一位置,就能利用关系运算符对其进行比较,遍历数组中的元素的方式:

    int* b = arr, * e = arr + sz;
    while (b<e)
    {
        //使用*b
        ++b;
    }

两个指针指向不相关的对象,则不能比较它们:

    int i = 0, sz = 42;
    int* p = &i, *e = &sz;
    //未定义的:p和e无关,因此比较毫无意义
    while(p<e)
  • p是空指针,允许给p加上或减去一个值为0的整型常量表达式
  • 两个空指针相减的结果为0

解引用和指针运算的交互

    int ia[] = {0,2,4,6,8};//含有5个整数的数组
    int last = *(ia + 4);//正确:把last初始化成8,也就是ia[4]的值

指针加法的圆括号也不可缺少:

last = *ia + 4;//正确:last=4等价于ia[0]+4

下标和指针

    int ia[] = {0,2,4,6,8};//含有5个整数的数组

ia[0]是一个使用了数组名字的表达式,对数组执行下标运算其实是对指向数组元素的指针执行下标运算:

    int i = ia[2];//ia转换成指向数组首元素的指针,ia[2]得到(ia+2)所指的元素
    int* p = ia;//p指向ia的首元素
    i = *(p + 2);//等价于i=ia[2]

只要指针指向的是数组中的元素(或者数组中尾元素的下一位置),都可以执行下标运算:

    int* p = &ia[2];//p指向索引为2的元素
    int j = p[1];//p[1]等价于*(p+1),就是ia[3]表示的那个元素
    int k = p[-2];//p[-2]是ia[0]表示的那个元素

内置的下标运算符可以处理负值,地址必须指向原来的指针所指同一数组中的元素。

转载于:https://www.cnblogs.com/suomeimei/p/10849375.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值