当数组下标是负数

假设整数位置的二维坐标点上都有一个温度,横坐标的范围是-3..2共6个点,纵坐标的范围是-4..3共8个点,因此,二维坐标点共48个,小宝定义了二维数组int data[6][8];
用data[0][0]存储坐标点(-3,-4)的温度,用data[0][1]存储坐标点(-3,-3)的温度,用data[0][2]存储坐标点(-3,-2)的温度,......,用data[5][7]存储坐标点(2,3)的温度,也就是用data[i][j]存储坐标点(i-3,j-4)的温度。
 
小宝感觉这样的坐标换算比较麻烦,于是他突发奇想,他想用data[-3][-4]存储坐标点(-3,-4)的温度,他想用data[-3][-3]存储坐标点(-3,-3)的温度,以此类推。小宝的愿望能实现吗?
 
一般情况下,数组是不允许越界的,看下面这个程序,给b赋值1,但是打印出来后,发现b不是1了,为什么呢?

#include <stdio.h>
int main()
{
int a[10];
int b;
b=1;
a[-1]=888;
printf("%d",b);
return 0;
}
因为越界了,然后这个数据占了b的位置
那data[-3][-4]会不会越界呢,最多越界多少字节,能计算出来吗?
根据定义int data[6][8];
假设data的起始地址是1000,data[s][t]的地址是1000+(s*8+t)*4
最后那个*4是因为每个整数占4个字节, (-3*8-4)*4=-28*4=-112

所以,最多越界112字节。有了这个数据以后,怎样避免数组越界非法改写其它数据呢?

#include <stdio.h>
int main()
{
int data[6][8];
int temp[28];
temp[0]=888;
data[-3][-4]=0;
printf("%d",temp[0]);
return 0;
}
看这个程序,data发生了越界,但是根据我们的计算,最多越界112字节,
而int temp[28]; 刚好是112字节。
temp[0]对应于data[-3][-4],temp[1]对应于data[-3][-3],以此类推。也就是说,data越界,只会改写temp,不会改写其它数据。我定义temp的目的,就是供data越界用的,没有其它用途,我不会在temp中存数据。这样做,数组虽然越界了,但是没有改写其它有用的数据,所以data[-3][-4]=0;能正确运行。

这样做,会不会造成存储空间的浪费呢?我认为,也可能没有造成存储空间浪费。

temp没存东西,但是它也占用内存。现在的情况是这样的:data本来是能存48个整数的,但是因为数组下标的使用方式改了,所以占用了temp的28个整数的空间,与此同时,data的最后28个整数的空间没有使用,一直闲着。假如我们需要长度为28的整型数组,正好可以把data的最后28个整数的位置利用起来,这样就达到“废物”利用的效果了。

#include <stdio.h>
int main()
{
int data[6][8];
int temp[28];
temp[0]=888;
data[-3][-4]=0;
printf("%d",temp[0]);
int *p;
p=(int *)data;
p=p+20;
//下面的语句演示如何使用data的没有使用的空间
int k;
for(k=0;k<28;k++)
p[k]=k;
return 0;
}
这28个数组元素的空间是112字节,假如我想用这112字节,定义一个长为10的整数数组(40字节),用剩余空间定义长为72的字符数组,该怎么做呢?
#include <stdio.h>
int main()
{
int data[6][8];
int temp[28];
temp[0]=888;
data[-3][-4]=0;
printf("%d",temp[0]);
int *p;
p=(int *)data;
p=p+20;
//下面的语句演示如何使用data的没有使用的空间
int k;
for(k=0;k<10;k++)
p[k]=k;
char *w;
w=(char *)data;
w=w+120;
for(k=0;k<72;k++)
w[k]='A';
return 0;
}
改完以后,p指向长为10的整型数组,w指向长为72的字符数组。
w=w+120;
这句是为什么呢?
因为我们已经知道,data数组自己用了20个整数的空间,
p用了10个整数的空间,所以应该越过(20+10)*4字节。
 
总结:首先,这个程序能正确运行,通过这个例子可以更好地理解数组空间的分配、数组越界和数组元素的地址的计算过程。但是不提倡这个做法,它会导致存储空间的管理更复杂。
 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值