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

对于C语言来说,效率是第一位,安全次之。所以没有数组边界检查,同时,在类型检查方面也是“强类型、弱检查”。

Type checking for a nonreference array parameter confirms only that the argument is a pointer of the same type as the elements in the array. Type checking does not verify that the argument actually points to an array of a specified size.

非引用数组形参的类型检查只是确保实参是和数组元素具有同样类型的指针,而不会检查实参实际上是否指向指定大小的数组。

It is up to any program dealing with an array to ensure that the program stays within the bounds of the array.

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

There are three common programming techniques to ensure that a function stays within the bounds of its array argument(s). The first places a marker in the array itself that can be used to detect the end of the array. C-style character strings are an example of this approach. C-style strings are arrays of characters that encode their termination point with a null character. Programs that deal with C-style strings use this marker to stop processing elements in the array.

有三种常见的编程技巧确保函数的操作不超出数组实参的边界。第一种方法是在数组本身放置一个标记来检测数组的结束。C 风格字符串就是采用这种方法的一个例子,它是一种字符数组,并且以空字符 null 作为结束的标记。处理 C 风格字符串的程序就是使用这个标记停止数组元素的处理。

A second approach is to pass pointers to the first and one past the last element in the array. This style of programming is inspired by techniques used in the standard library.

第二种方法是传递指向数组第一个和最后一个元素的下一个位置的指针。这种编程风格由标准库所使用的技术启发而得。

Using this approach, we could rewrite printValues and call the new version as follows:

使用这种方法重写函数 printValues 并调用该函数,如下所示:

     void printValues(const int *beg, const int *end)
     {
         while (beg != end) {
             cout << *beg++ << endl;
          }
     }
     int main()
     {
         int j[2] = {0, 1};
         // ok: j is converted to pointer to 0th element in j
         //     j + 2 refers one past the end of j
         printValues(j, j + 2);
         return 0;
     }

The loop inside printValues looks like other programs we've written that used vector iterators. We march the beg pointer one element at a time through the array. We stop the loop when beg is equal to the end marker, which was passed as the second parameter to the function.

printValues 中的循环很像用 vector 迭代器编写的程序。每次循环都使 beg 指针指向下一个元素,从而实现数组的遍历。当 beg 指针等于结束标记时,循环结束。结束标记就是传递给函数的第二个形参。

When we call this version, we pass two pointers: one to the first element we want to print and one just past the last element. The program is safe, as long as we correctly calculate the pointers so that they denote a range of elements.

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

A third approach, which is common in C programs and pre-Standard C++ programs, is to define a second parameter that indicates the size of the array.

第三种方法是将第二个形参定义为表示数组的大小,这种用法在 C 程序和标准化之前的 C++ 程序中十分普遍。

Using this approach, we could rewrite printValues one more time. The new version and a call to it looks like:

用这种方法再次重写函数 printValues,新版本及其调用如下所示:

     // const int ia[] is equivalent to const int* ia
     // size is passed explicitly and used to control access to elements of ia
     void printValues(const int ia[], size_t size)
     {
          for (size_t i = 0; i != size; ++i) {
              cout << ia[i] << endl;
          }
     }
     int main()
     {
         int j[] = { 0, 1 }; // int array of size 2
         printValues(j, sizeof(j)/sizeof(*j));
         return 0;
     }

This version uses the size parameter to determine how many elements there are to print. When we call printValues, we must pass an additional parameter. The program executes safely as long as the size passed is no greater than the actual size of the array.

这个版本使用了形参 size 来确定要输出的元素的个数。调用 printValues 时,要额外传递一个形参。只要传递给函数的 size 值不超过数组的实际大小,程序就能安全运行。

三种方法可用三个关键字概括:flag, range, size。

-End-

展开阅读全文

页面更新:2024-03-08

标签:数组   边界   函数   重写   字符串   指针   标记   字符   元素   大小   风格   常见   位置   类型   结束

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top