C++7.2.5数组做实参---避免越界

本文探讨了在C++中如何安全地处理传递给函数的数组,包括通过放置结束标记、传递边界指针和显示传递数组大小。强调了在函数中确保不超出数组边界的重要性,并比较了指针形参和引用形参在处理数组时的优缺点。同时,提出了计算数组元素之和的函数实现方法。

简介

============================================================================================================

一、传递给函数的数组的处理

1、处理数组的程序要确保程序停留在数组的边界内

  • 非引用数组形参的类型检查只是确保实参是和数组元素具有相同类型的指针,而不会检查实参实际上是否指向指定大小的数组。(看7.2.4 数组的引用做形参则是要求大小也要一致的)

  • 引用类型就会检查实参数组的大小是否和形参数组大小一致。(7.2.4节)

  • 任何处理数组的程序都要确保程序停留在数组的边界内

有三种常见的编程技巧确保函数的操作不超出数组实参的边界。

  • 在数组本身放置一个标记来检测数组的结束, C风格字符串就是采用空字符null作为结束的标记(含有‘\0’结束的字符数组);

  • 传递指向数组第一个和最后一个元素的下一个位置的指针。

  • 将第二个形参定义为表示数组的大小。

2、使用标准库规范

  • 被调用的函数形参里边一个形参是传递指向数组第一个,另一个形参是最后一个元素的下一个位置的指针。

  • 调用这个函数需要传递两个指针:一个指向要输出的第一个元素,另一个则指向最后一个元素的下一个位置,只要正确计算指针,使他们标记一段有效的元素范围,程序就会安全。

void printValues(const int *beg,const int *end)
{
   while(beg!=end){
      cout<<*beg++<<endl;
}//函数的循环很像用vector迭代器编写的程序。每次循环都使beg指针指向下一个元素,从而实现数组的遍历。当beg指针等于结束标记时,循环结束,结束标记就是传递给函数的第二个形参。

}

int main(){
    int j[2]={0,1};
    printValues(j,j+2);//j指向数组的第一个元素,j+2指向数组最后一个元素的下一个位置
    return 0;

}

3、显示传递表示数组大小的形参

将被调用函数的第二个形参定义为表示数组的大小。

void printValues(const int ia[],size_t size)
{
for (size_t i=0;i!=size;i++){
     cout<<ia[i]<<endl;
//用size来确定要输出的元素的个数,只要传递给函数的size值不超过数组的实际大小,程序就能安全运行。
}
}

int main()
{  int j[]={0,1};
printValues(j,sizeof(j)/sizeof(*j));//5.8节上,sizeof(数组名)求的是整个数组的所有元素占有的内存大小。
//sizeof(*j)=sizeof(j[0])=sizeof(int类型的数)=4
return 0;
}

习题7.12 什么时候使用指针形参?什么时候使用引用形参?解释两者的优缺点。

  1. 当函数需要处理数组且函数体不依赖于数组的长度时应使用指针形参,其他情况下应该使用引用形参;

  2. 指针形参的优点是可以明确地表示函数所操纵的是指向数组元素的指针,而不是数组本身,而且可以使用任意长度的实参数组来调用函数(而引用形参是实参和形参必须对应);

  3. 指针形参的缺点是函数体不能依赖于数组的长度,否则容易造成数组内存的越界访问,从而产生错误的结果或者导致程序崩溃;

  4. 引用形参的优点是在函数体中依赖数组的长度是安全的,缺点是限制了可以传递的实参数组,只能使用长度匹配的实参数组来调用函数(就是实参)。

//习题 7.13 计算数组元素之和。要求编写函数三次,每次以不同的方法处理数组边界

int sum1(const int *begin,const int * end)
{
    int sum=0;
    while(begin!=end){
        sum+=*begin++;
    }
    return sum;
}
int sum2(const int ia[],size_t size){
    int sum=0;
    for(size_t ix=0;ix!=size;ix++){
       sum+=ia[ix];
    }
    return sum;
}
int sum3(int *begin,size_t size){
    int sum=0;
    int *p=begin;
    while(p!=begin+size){
    sum+=*p++;
    }
    return sum;
}

    int main(){
   int ia[]={1,2,3,4};
   cout<<sum1(ia,ia+4)<<endl;
   cout<<sum2(ia,4)<<endl;
   cout<<sum3(ia,4)<<endl;
    return 0;

}
//习题7.14
double vectorSum(vector<double>::iterator begin,vector<double>::iterator end)
{
double sum=0.0;//double类型初始化
while(begin!=end){
 sum+=*begin++;
}
return sum;
}
    int main(){
   vector<double> dvec;
   double dval;
   while(cin>>dval)
       dvec.push_back(dval);   //初始化vector
 cout<<  vectorSum(dvec.begin(),dvec.end())<<endl;
    return 0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值