说明:大部分内容参考自Notes on Data Structures and Programming Techniques by James Aspnes
Arrays and functions 数组与函数
下面一段代码说的是,pass一个数组到函数,计算数组前n个元素的和:
/* compute the sum of the first n elements of array a */
/* 前提是a的size大于等于n */
int sumArray(int n, const int *a) // int sumArray(int n, const int a[])
{
int i;
int sum = 0;
for(i = 0; i < n; i++)
sum += a[i];
return sum;
}
使用const确保a[ ]的内容不会被更改。下面这种写法也OK:
int sumArray(int n, const int a[])
{
const int *an;
int sum = 0;
an = a + n;
while(a < an)
sum += *a++;
return sum;
}
Multidimensional arrays 多维数组
在C语言中,至少有两种方法来创建多维数组,第一种方法就是直接处理成一维数组(这里就不讨论了),第二种方法是使用指针和malloc来动态分配内存并创建数组。第二种方式的一个好处是,我们可以通过a[i][j]这种方式来获取数组元素,坏处是数组并不是连续的(the array is not contiguous)。
下面这个程序,可以学到的东西包括:在C语言里面,如何通过指针和动态分配内存来创建多维数组。比如二维用到void **a,三维就用到void ***a,思路是一样的。使用malloc之后,一定要记得释放内存。
在malloc2d(size_t numRows, size_t rowSize)里,a = malloc(sizeof(void *) * (numRows + 1))这一步是创建了(numRows + 1)个指针,a指向这个指针数组,后面这个指针数组中的每一个指针指向具体的每一排。用图来解释就是:
具体代码:
#include <stdlib.h>
#include <stdio.h>
/* free a 2d array created by malloc2d */
void free2d(void **a) {
void **row;
/* first free rows */
for(row = a; *row != 0; row++)
free(*row);
/* then free array of rows */
free(a);
}
/* returns a two-dimensional array with numRows rows and
** rowSize bytes per row, or 0 on allocation failure.
** The caller is responsible for freeing the result with free2d. */
void ** malloc2d(size_t numRows, size_t rowSize) {
void **a;
size_t i;
/* The last element is 0, so free2d can detect the last row */
/* one extra for sentinel */
/* 个人理解,这里引入sentinel是因为把malloc2d()和free2d()跟main函数分开了 */
a = malloc(sizeof(void *) * (numRows + 1));
if(a == 0) {
/* malloc failed */
return 0;
}
/* now allocate the actual rows */
for(i = 0; i < numRows; i++) {
a[i] = malloc(rowSize);
if(a[i] == 0) {
/* note that 0 in a[i] will stop free2d after it frees previous rows */
free2d(a);
return 0;
}
}
/* initialize the sentinel value */
a[numRows] = 0;
return a;
}
int main(int argc, char **argv) {
int rows, cols;
int **a;
int i, j;
if(argc != 3) {
fprintf(stderr, "Usage: %s rows cols\n", argv[0]);
return 1;
}
/* else */
rows = atoi(argv[1]);
cols = atoi(argv[2]);
/* note that void ** is not converted automatically,
so we need an explicit cast */
a = (int **) malloc2d(rows, cols * sizeof(int));
if(a == 0) {
fprintf(stderr, "malloc2d failed, exiting\n");
return 2;
}
/* 阵列初始化 + 打印阵列 */
for(i = 0; i < rows; i++)
for(j = 0; j < cols; j++)
a[i][j] = i - j;
for(i = 0; i < rows; i++) {
for(j = 0; j < cols; j++) {
printf("%4d", a[i][j]);
}
putchar('\n');
}
free2d((void **) a); /* always clean up */
return 0;
}