C++中将数组形参作为形参时防止访问越界的几种方法

关于指针地址访问越界的问题
[问题点数:100分,结帖人xw_158]
本版专家分:0
结帖率 100%
CSDN今日推荐
本版专家分:33864
2012年5月 C/C++大版内专家分月排行榜第一
2012年7月 C/C++大版内专家分月排行榜第二2012年6月 C/C++大版内专家分月排行榜第二
本版专家分:0
结帖率 100%
本版专家分:0
结帖率 100%
本版专家分:545
本版专家分:0
结帖率 100%
匿名用户不能发表回复!|
CSDN今日推荐为什么静态数组越界可以正常访问?
[问题点数:40分,结帖人fox_liucx]
本版专家分:73
CSDN今日推荐
本版专家分:33534
2014年7月 C/C++大版内专家分月排行榜第二2014年5月 C/C++大版内专家分月排行榜第二
2014年10月 C/C++大版内专家分月排行榜第三2014年4月 C/C++大版内专家分月排行榜第三
本版专家分:368097
2017年 总版技术专家分年内排行榜第一
2014年 总版技术专家分年内排行榜第二
2013年 总版技术专家分年内排行榜第三
2012年 总版技术专家分年内排行榜第七
本版专家分:32823
2013年11月 Linux/Unix社区大版内专家分月排行榜第一2013年11月 专题开发/技术/项目大版内专家分月排行榜第一2013年9月 C/C++大版内专家分月排行榜第一2013年9月 专题开发/技术/项目大版内专家分月排行榜第一2013年8月 C/C++大版内专家分月排行榜第一
2013年12月 C/C++大版内专家分月排行榜第二2013年12月 Linux/Unix社区大版内专家分月排行榜第二2013年11月 C/C++大版内专家分月排行榜第二2013年10月 C/C++大版内专家分月排行榜第二
本版专家分:694
本版专家分:4959
2015年8月 硬件/嵌入开发大版内专家分月排行榜第一2015年7月 VC/MFC大版内专家分月排行榜第一2015年5月 VC/MFC大版内专家分月排行榜第一2015年4月 VC/MFC大版内专家分月排行榜第一2015年3月 VC/MFC大版内专家分月排行榜第一2015年1月 硬件/嵌入开发大版内专家分月排行榜第一2013年12月 VC/MFC大版内专家分月排行榜第一2013年11月 VC/MFC大版内专家分月排行榜第一2013年6月 VB大版内专家分月排行榜第一2013年5月 VB大版内专家分月排行榜第一2013年1月 VB大版内专家分月排行榜第一2012年12月 VB大版内专家分月排行榜第一
2015年9月 VC/MFC大版内专家分月排行榜第二2015年7月 硬件/嵌入开发大版内专家分月排行榜第二2014年5月 VC/MFC大版内专家分月排行榜第二2014年3月 VC/MFC大版内专家分月排行榜第二2013年10月 VB大版内专家分月排行榜第二2013年7月 VB大版内专家分月排行榜第二2012年5月 VB大版内专家分月排行榜第二2012年4月 VB大版内专家分月排行榜第二2012年2月 VB大版内专家分月排行榜第二2011年11月 VB大版内专家分月排行榜第二
2015年11月 VC/MFC大版内专家分月排行榜第三2015年6月 VC/MFC大版内专家分月排行榜第三2015年2月 VC/MFC大版内专家分月排行榜第三2014年1月 VC/MFC大版内专家分月排行榜第三2012年3月 VB大版内专家分月排行榜第三2011年12月 VB大版内专家分月排行榜第三2011年10月 VB大版内专家分月排行榜第三
本版专家分:574
本版专家分:2629
本版专家分:6
本版专家分:438
结帖率 98.11%
本版专家分:66
本版专家分:438
结帖率 98.11%
本版专家分:18035
本版专家分:544
本版专家分:544
本版专家分:3
本版专家分:325
匿名用户不能发表回复!|
CSDN今日推荐C/C++面试题--数组作为函数参数的几个问题
void fun(int array[10])
int *p = &array[-1];
//p = &array[0] - 1;
cout&&"function:fun()"&&
cout&&"address of array: "&&array&&
cout&&"address of p: "&&p&&
cout&&"sizeof(array): "&&sizeof(array)&&
array[2]= 80;
cout&&"---------------change array[2]-------------"&&
cout&&"array[2]= "&&array[2]&&
int main(int argc, char* argv[])
int array[5] = {5, 4, 3, 2, 1};
cout&&"function:main()"&&
cout&&"address of array: "&&array&&
cout&&"sizeof(array): "&&sizeof(array)&&
cout&&"---------------before change array[2]-------------"&&
cout&&"array[2]= "&&array[2]&&
fun(array);
cout&&"---------------after change array[2]-------------"&&
cout&&"array[2]= "&&array[2]&&
今天面试遇到了上面这个问题:用下标-1访问形参是数组的参数,问该调用方式是否有问题?
在搞清楚这个问题之前,先得明白两个问题:1. 数组作为函数参数,传值还是传址?
2. void fun(int array[10])和void fun(int array[])有区别么?
3. 函数参数中的数组元素个数能否确定?输出结果:
function:main()
address of array: 0012FF6C
sizeof(array): 20
---------------before change array[2]-------------
array[2]= 3
function:fun()
address of array: 0012FF6C
address of p: 0012FF68
sizeof(array): 4
---------------change array[2]-------------
array[2]= 80
---------------after change array[2]-------------
array[2]= 80
由输入地址都是0012FF6C以及fun函数内部修改下标为2的数组元素,即修改了main函数中定义的array数组元素值,由此我们可以得出结论:数组作为函数参数是传址,该地址就是数组的首地址。
由于在fun函数中sizeof(array)求得值是4,所以可知:函数参数中的数组元素个数信息已经丢失,函数已经把数组作为指针来传递。因而void fun(int array[10])和void fun(int array[])根本就没区别。
再来看:int *p = &array[-1];我们把它拆解成:p = &array[0] - 1;实际上就是array地址-1,由于是int型指针,所以的array地址减4,输入结果也是这样的。
没有更多推荐了,
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!还没有账号
用户名或密码错误
C++中数组作为形参传递给函数时把数组视为指针,并没有将数组的长度信息传递给函数,因而在函数中稍有不慎就会造成数组内存的越界访问。为了避免这个问题,下面根据书上给的内容做了一点总结和说明。
数组形参的定义
void func(int *) {/* ...*/}
void func(int[]) {/* ... */}
void func(int[10]) {/* ...*/}
上面三种形参表示方式都是合法和等价的,可以看到C++将数组视为指针。另外第三种表示方式看上去在方括号中用一个常量指定了数组的长度,但事实上编译器忽略了这一方式指定的数组长度,在函数调用时即使你给func函数传递一个长度不为10的数组编译器同样可以让你通过,只不过这在实际运行中可能造成数组内存的越界访问。(注:这种表示方式要和下面介绍的数组引用相区分开来)
因为C++并不支持将数组的长度信息自动传递给函数,所以我们在编写代码时必须采取措施来避免数组形参带来的越界访问问题,下面给出几种方法
显示传递数组长度:在函数定义的参数列表中加多一个表示数组大小的参数,这种做法比较常见,举个例子:void func(int arr[], size_t size)
for (size_t i = 0; i < i++)
// operation
显示指定数组开始和结束的位置:这种编程风格由标准库所使用的技术启发而得,常见于迭代器的使用,举个例子:void func(int *begin, int *end)
for (int *pt = pt != pt++)
// operation
显示添加结束的标记:在数组末尾加多一个标识元素用来检测数组的结束,常见的例子是C风格字符串,它是一种字符数组,并且以空字符null作为结束的标记void func(char *cstr)
for (int i = 0; '\0' != cstr[i]; i++)
// operation
通过引用传递数组:如果形参是数组的引用,编译器不会将数组实参转化为指针,而是传递数组的引用本身void func(int (&arr)[10])
for (int i = 0; i < 10; i++)
// operation
int main()
int size = 20;
int iarray[size] = {0};
func(iarray); // error
不过这种方式编译器有着严格的规定,使用时要注意以下几点:
实参和形参的数组的长度都必须是常量,包括字面值常量(例如上面的数字10)和const修饰的常量(const int Size = 20; void func(int (&arr)[Size]) { } ),例如上面在main函数中调用func函数错误的原因在于实参数组iarray定义时用了变量size来指定长度。这样做确保在编译时就能检测出可能出现的数组长度不一致的错误,而不至于等到运行时造成更严重的后果
函数定义时&和变量名要用括号括起来,表示变量arr是指向int[10]型数组的指针
C++中的引用时允许修改原始数据,因此在函数调用时要谨慎考虑,如果不允许调用函数func对数组进行修改,在定义func函数时使用const修饰数组( void func(const int (&arr)[10]) )
全部评论: 0 条
Copyright (C)2017 Noneone All Rights Reserved 皖ICP备号比来比去比卡丘
C++数组越界了还是可以输出越界的字符
这两天写代码遇到了一个奇怪的事,字符二维数组越界了,但是仍然可以输出字符。废话不多说先上代码int main() {
char frame[5][2] = {
{'1','1'},
{'1','0'},
{'1','1'},
{'0','0'},
{'0','1'} };
for (int i = 0; i & 5;i++) {
for (int j = 0; j & 2;j++) {
cout && frame[i][j];
system("pause");
} 正常情况下跑一遍看看结果没有任何问题,下面修改下代码,把变量j的上限改为3int main() {
char frame[5][2] = {
{'1','1'},
{'1','0'},
{'1','1'},
{'0','0'},
{'0','1'} };
for (int i = 0; i & 5;i++) {
for (int j = 0; j & 3;j++) {
cout && frame[i][j];
system("pause");
}再看看运行结果仍然可以输出字符,数组越界居然不报错。为了搞明白是什么原因,再修改下代码,让二维数组有一行元素不赋初值int main() {
char frame[6][2] = {
{'1','1'},
{'1','0'},
{'1','1'},
{'0','0'},
{'0','1'} };
for (int i = 0; i & 6;i++) {
for (int j = 0; j & 4;j++) {
cout && frame[i][j];
system("pause");
} 看看结果感觉这数字有点规律啊,以及最后一个熟悉的“烫”字。再仔细一看原来第一行的“多余”的两位,和第二行元素一样。顿时豁然开朗,应该是二维数组开辟内存空间时相邻两行的地址是连在一起的,即上一行最后一个元素的地址末尾,是这一行首元素地址的开始。下面进行另外一个实验 我们输出下frame[0]看看 按道理这代表二维数组的第一行结果却是全给我输出了。可是有的时候我只想取二维数组的一行怎么办呢?1.设置循环参数时,一行有多少个元素就设定循环上限为多少2. 参考 http://blog.csdn.net/sinat_/article/details/,把二维数组的一行作为源参数(*src),一维数组作为目标参数(*dest),然后计算正确的字节数就可以了。
没有更多推荐了,
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!}

我要回帖

更多关于 python 防止数组越界 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信