第六章 “另类”数组
来源:百度文库 编辑:神马文学网 时间:2024/04/27 23:36:09
第六章 “另类”数组
动态数组与字符串常量可算是两种“另类”数组。
VLA可变长数组并不为C89所支持,C99才开始支持VLA。但如果想在只支持C89的编译环境中使用VLA的话,怎么办呢?我们可以用动态数组来“模拟”,动态数组在矩阵的运算中很常见,常用来向函数传递一个大小可变的矩阵。动态数组的原理,是利用一块或多块动态分配的内存存储各维的首地址,这样就可以p[i][j]的形式访问数组的数据了。但是,动态数组并非真正的数组,它只是对数组的一种模拟。由于具有数组类型的数组名是系统行为,在用户这一级没法做到,因此只能以指针的形式存放首地址,sizeof(p)和sizeof(p[i])结果都是4字节。虽然动态数组是依靠动态分配内存来建立的,但动态的意义并非来自这里,而是指大小可变。笔者觉得用“动态数组”这个名称来命名非常适合,既不失大小可变的特征,又可以跟VLA可变长数组区分开来。
下面是建立动态数组的示例:
#include
#include
void computedata(int *, int, int);
int main(void)
{
int iData[100], x, y;
do
{
printf("The product obtained by multiplying x and y must be less than 100!");
printf("x=");
scanf("%d", &x);
printf("y=");
scanf("%d", &y);
}
while(x*y > 100);
computedata(iData, x, y);
return 0;
}
void computedata(int *ipSource, int iRow, int iColumn)
{
int **ipTemp, i, j;
ipTemp = (int **)malloc(iRow*sizeof(int*));
for(i=0; ifor(i=0; ifree(ipTemp);
return;
}
以上示例把动态数组ipTemp的元素都加了1,由于只是示例,笔者省略了检测数据合法性的代码。iRow是第一维上界,iColumn是第二维上界,iData是源数据缓冲区,iRow*iColumn的积不能超过iData缓冲区的大小,否则就会越界了,但可以比它小。示例中iData被定义为一维数组,当然根据自己的需要也可以用其它类型的缓冲区代替,例如动态分配的一块内存,或者多维数组,如果是多维数组,例如三维数组int iData[10][10][10],调用computedata函数时,实参iData得做一些转换:
computedata((int *)iData, x, y);或者computedata(&iData[0][0][0], x, y);都可以。
ipSource指针用来传递缓冲区的首地址,这个指针由于要用来计算各维的地址,因此最好定义为一级指针,这样比较方便。ipTemp是一个二级指针,这是因为它指向的那块内存存放的是指针,这些指针指向各维的首地址,对ipTemp的元素来说,ipTemp就是二级的。最后记得free(ipTemp);
以上是定义一个二维动态数组的例子,多维动态数组的创建方法跟这个类似,下面给出三维动态数组的代码:
void computedata(int *ipSource, int iHigh, int iRow, int iColumn)
{
int ***ipTemp, i, j, k;
ipTemp = (int ***)malloc(iHigh*sizeof(int**));
for(i=0; ifor(i=0; ifor(i=0; ifor(i=0; ifree(ipTemp);
return;
}
下面来讨论字符串常量。
众所周知,C语言是没有字符串变量的,因而,C89规定,字符串常量就是一个字符数组。因此,尽管字符串常量的外部表现形式跟数组完全不同,但它的确是一个真正的数组,实际上,字符串常量本身就是这个数组的首地址,并且具有数组类型,对一个字符串常量进行sizeof运算,例如sizeof("abcdefghi"),结果是10,而不是4。字符串常量与一般数组的主要区别,是字符串常量存放在静态存储区,而一般数组(非static)则是在栈中静态分配的。由于字符串常量是数组首地址,因此可以数组引用的形式使用它,例如:
printf("%s", &"abcdefghi"[4]);
这将打印出字符串efghi。还可以这样:
printf("%s", "abcdefghi"+4);
同样打印出字符串efghi。实际上,&"abcdefghi"[4]等价于&*("abcdefghi"+4),去掉&*后,就是"abcdefghi"+4了。
我们可以利用字符串常量这些特性写出一些有趣的程序来,例如:
#include
int iLine=1;
int main(void)
{
printf("%*s\n", 7-(iLine>4?iLine-4:4-iLine), "*******"+2*(iLine>4?iLine-4:4-iLine));
if(++iLine != 8) main();
return 0;
}
这个程序不使用任何数组形式的引用,不使用循环,就可以打印出用*号组合出来的菱形。当然,笔者并非鼓励大家编写这样的代码,但通过这样的例子加深对字符串常量的认识,仍然是非常重要的。
本文引用通告地址: http://blog.csdn.net/megaboy/services/trackbacks/482774.aspx
[点击此处收藏本文]
动态数组与字符串常量可算是两种“另类”数组。
VLA可变长数组并不为C89所支持,C99才开始支持VLA。但如果想在只支持C89的编译环境中使用VLA的话,怎么办呢?我们可以用动态数组来“模拟”,动态数组在矩阵的运算中很常见,常用来向函数传递一个大小可变的矩阵。动态数组的原理,是利用一块或多块动态分配的内存存储各维的首地址,这样就可以p[i][j]的形式访问数组的数据了。但是,动态数组并非真正的数组,它只是对数组的一种模拟。由于具有数组类型的数组名是系统行为,在用户这一级没法做到,因此只能以指针的形式存放首地址,sizeof(p)和sizeof(p[i])结果都是4字节。虽然动态数组是依靠动态分配内存来建立的,但动态的意义并非来自这里,而是指大小可变。笔者觉得用“动态数组”这个名称来命名非常适合,既不失大小可变的特征,又可以跟VLA可变长数组区分开来。
下面是建立动态数组的示例:
#include
#include
void computedata(int *, int, int);
int main(void)
{
int iData[100], x, y;
do
{
printf("The product obtained by multiplying x and y must be less than 100!");
printf("x=");
scanf("%d", &x);
printf("y=");
scanf("%d", &y);
}
while(x*y > 100);
computedata(iData, x, y);
return 0;
}
void computedata(int *ipSource, int iRow, int iColumn)
{
int **ipTemp, i, j;
ipTemp = (int **)malloc(iRow*sizeof(int*));
for(i=0; i
return;
}
以上示例把动态数组ipTemp的元素都加了1,由于只是示例,笔者省略了检测数据合法性的代码。iRow是第一维上界,iColumn是第二维上界,iData是源数据缓冲区,iRow*iColumn的积不能超过iData缓冲区的大小,否则就会越界了,但可以比它小。示例中iData被定义为一维数组,当然根据自己的需要也可以用其它类型的缓冲区代替,例如动态分配的一块内存,或者多维数组,如果是多维数组,例如三维数组int iData[10][10][10],调用computedata函数时,实参iData得做一些转换:
computedata((int *)iData, x, y);或者computedata(&iData[0][0][0], x, y);都可以。
ipSource指针用来传递缓冲区的首地址,这个指针由于要用来计算各维的地址,因此最好定义为一级指针,这样比较方便。ipTemp是一个二级指针,这是因为它指向的那块内存存放的是指针,这些指针指向各维的首地址,对ipTemp的元素来说,ipTemp就是二级的。最后记得free(ipTemp);
以上是定义一个二维动态数组的例子,多维动态数组的创建方法跟这个类似,下面给出三维动态数组的代码:
void computedata(int *ipSource, int iHigh, int iRow, int iColumn)
{
int ***ipTemp, i, j, k;
ipTemp = (int ***)malloc(iHigh*sizeof(int**));
for(i=0; i
return;
}
下面来讨论字符串常量。
众所周知,C语言是没有字符串变量的,因而,C89规定,字符串常量就是一个字符数组。因此,尽管字符串常量的外部表现形式跟数组完全不同,但它的确是一个真正的数组,实际上,字符串常量本身就是这个数组的首地址,并且具有数组类型,对一个字符串常量进行sizeof运算,例如sizeof("abcdefghi"),结果是10,而不是4。字符串常量与一般数组的主要区别,是字符串常量存放在静态存储区,而一般数组(非static)则是在栈中静态分配的。由于字符串常量是数组首地址,因此可以数组引用的形式使用它,例如:
printf("%s", &"abcdefghi"[4]);
这将打印出字符串efghi。还可以这样:
printf("%s", "abcdefghi"+4);
同样打印出字符串efghi。实际上,&"abcdefghi"[4]等价于&*("abcdefghi"+4),去掉&*后,就是"abcdefghi"+4了。
我们可以利用字符串常量这些特性写出一些有趣的程序来,例如:
#include
int iLine=1;
int main(void)
{
printf("%*s\n", 7-(iLine>4?iLine-4:4-iLine), "*******"+2*(iLine>4?iLine-4:4-iLine));
if(++iLine != 8) main();
return 0;
}
这个程序不使用任何数组形式的引用,不使用循环,就可以打印出用*号组合出来的菱形。当然,笔者并非鼓励大家编写这样的代码,但通过这样的例子加深对字符串常量的认识,仍然是非常重要的。
本文引用通告地址: http://blog.csdn.net/megaboy/services/trackbacks/482774.aspx
[点击此处收藏本文]
第六章 “另类”数组
第六章 “另类”数组
第三章 数组的解剖学
第三章 数组的解剖学
第五章 VB中的数组
CSDN技术中心 第二章 再一次吃惊----数组的数组与多维数组的区别
第二章 再一次吃惊----数组的数组与多维数组的区别 - 飞天御剑流
第六章
第六章
第六章
第五章 指向数组的指针
第五章 指向数组的指针
CSDN技术中心 第三章 数组的解剖学
CSDN技术中心 第五章 指向数组的指针
CSDN技术中心 第三章 数组的解剖学
指针数组和数组指针
第六章 框架
第六章 雪肤红画耀幽烛
第六章 水资源枯竭
第六章 整体性向
恋爱日记第六章
长街 第六章
初晴微雨 第六章
走西口 第六章