19 {
20 printf("b[%d]=%d ",j,b[j]);
21 }
22 printf("\nc[MAX2]:\n");
23 for(z=0;z<MAX2;z++)
24 {
25 printf("c[%d]=%d ",z,c[z]);
26 }
27 printf("\n");
28 return 0;
29}
运行结果为:
1 a[MAX]:
2 a[0]=1 a[1]=2 a[2]=3 a[3]=4 a[4]=5 a[5]=6 a[6]=7 a[7]=8 a[8]=9 a[9]=10
3 b[MAX1]:
4 b[0]=1 b[1]=2 b[2]=3 b[3]=4 b[4]=5 b[5]=0 b[6]=0 b[7]=0 b[8]=0 b[9]=0 b[10]=6 b[11]=7 b[12]=8 b[13]=9 b[14]=10
5 c[MAX2]:
6 c[0]=1 c[1]=6 c[2]=7 c[3]=8 c[4]=9 c[5]=10
对数组做越界检查,确保索引值位于合法的范围之内
要避免数组越界,除了上面所阐述的显式指定数组的边界之外,还可以在数组使用之前进行越界检查,检查数组的界限和字符串(也以数组的方式存放)的结束,以保证数组索引值位于合法的范围之内 。例如,在写处理数组的函数时,一般应该有一个范围参数;在处理字符串时总检查是否遇到空字符‘\0’ 。
来看下面一段代码示例:
1#define ARRAY_NUM 10
2int *TestArray(int num,int value)
3{
4 int *arr=NULL;
5 arr=(int *)malloc(sizeof(int)*ARRAY_NUM);
6 if(arr!=NULL)
7 {
8 arr[num]=value;
9 }
10 else
11 {
12 /*处理arr==NULL*/
13 }
14 return arr;
15}
从上面的int*TestArray(int num,int value)函数中不难看出,其中存在着一个很明显的问题,那就是无法保证 num 参数是否越界(即当num>=ARRAY_NUM的情况) 。因此,应该对 num 参数进行越界检查,示例代码如下所示:
1int *TestArray(int num,int value)
2{
3 int *arr=NULL;
4 /*越界检查(越上界)*/
5 if(num<ARRAY_NUM)
6 {
7 arr=(int *)malloc(sizeof(int)*ARRAY_NUM);
8 if(arr!=NULL)
9 {
10 arr[num]=value;
11 }
12 else
13 {
14 /*处理arr==NULL*/
15 }
16 }
17 return arr;
18}
这样通过if(num<ARRAY_NUM)语句进行越界检查,从而保证 num 参数没有越过这个数组的上界 。现在看起来,TestArray() 函数应该没什么问题,也不会发生什么越界错误 。
文章插图
但是,如果仔细检查,TestArray() 函数仍然还存在一个致命的问题,那就是没有检查数组的下界 。由于这里的 num 参数类型是 int 类型,因此可能为负数 。如果 num 参数所传递的值为负数,将导致在 arr 所引用的内存边界之外进行写入 。
当然,你可以通过向if(num<ARRAY_NUM)语句里面再加一个条件进行测试,如下面的代码所示:
if(num>=0&&num<ARRAY_NUM)
{
}
但是,这样的函数形式对调用者来说是不友好的(由于 int 类型的原因,对调用者来说仍然可以传递负数,至于在函数中怎么处理那是另外一件事情),因此,更佳的解决方案是将 num 参数声明为 size_t 类型,从根本上防止它传递负数,示例代码如下所示:
1int *TestArray(size_t num,int value)
2{
3 int *arr=NULL;
4 /*越界检查(越上界)*/
5 if(num<ARRAY_NUM)
6 {
7 arr=(int *)malloc(sizeof(int)*ARRAY_NUM);
8 if(arr!=NULL)
9 {
10 arr[num]=value;
11 }
12 else
13 {
14 /*处理arr==NULL*/
15 }
16 }
17 return arr;
18}
获取数组的长度时不要对指针应用 sizeof 操作符
在 C 语言中,sizeof 这个其貌不扬的家伙经常会让无数程序员叫苦连连 。同时,它也是各大公司争相选用的面试必备题目 。简单地讲,sizeof 是一个单目操作符,不是函数 。其作用就是返回一个操作数所占的内存字节数 。其中,操作数可以是一个表达式或括在括号内的类型名,操作数的存储大小由操作数的类型来决定 。例如,对于数组int a[5],可以使用sizeof(a)来获取数组的长度,使用sizeof(a[0])来获取数组元素的长度 。
但需要注意的是,sizeof 操作符不能用于函数类型、不完全类型(指具有未知存储大小的数据类型,如未知存储大小的数组类型、未知内容的结构或联合类型、void 类型等)与位字段 。例如,以下都是不正确形式:
1/*若此时max定义为intmax();*/
2sizeof(max)
3/*若此时arr定义为char arr[MAX],且MAX未知*/
4sizeof(arr)
5/*不能够用于void类型*/
6sizeof(void)
7/*不能够用于位字段*/
8struct S
9{
10 unsigned int f1 : 1;
11 unsigned int f2 : 5;
12 unsigned int f3 : 12;
13};
14sizeof(S.f1);
了解 sizeof 操作符之后,现在来看下面的示例代码:
推荐阅读
- 毛豆怎么吃,毛豆新吃法好吃到爆?
- 我想贷款10万哪里好贷 一分利息10万一年多少钱怎么算
- 在手机上怎么申请办医保卡 第一次办医保卡在哪里办
- 白皮甜瓜的种植与管理 白皮甜瓜怎么挑选
- 客一和客二的收费标准 客一客二客三怎么区分
- 迅雷下载加速教程 迅雷下载怎么加速
- 中兴双屏手机详细配置 中兴双屏手机怎么样
- 中兴axon天机体验 中兴axon天机怎么样
- 辣椒炒驴肉怎么炒好吃,熟驴肉怎么吃好吃家庭做法?
- 怎么算八字合不合?