是否有可能编写一个可以在C中转储任意维int数组的函数?

时间:2011-07-29 04:21:53

标签: c arrays

最后,如果我想转储数组,只需:

int array[dim1][dim2]..;

A(array, dim1, dim2, dim3, dim4...);

是否可以在C?

更新

如何在array中定义A(array, dim1, dim2, dim3, dim4...);的类型,以便编译器不会发出任何警告?

2 个答案:

答案 0 :(得分:5)

对A的调用必须指明维度的数量,并提供每个维度的大小。使用一些C99:

代码

#include <assert.h>
#include <stdarg.h>
#include <stdio.h>

extern void A(int *base, int ndims, ...);
extern void B(void);

void A(int *base, int ndims, ...)
{
    assert(ndims > 0);
    int     dims[ndims];
    int     size = 1;
    va_list args;
    va_start(args, ndims);
    for (int i = 0; i < ndims; i++)
    {
        dims[i] = va_arg(args, int);
        size *= dims[i];
    }
    va_end(args);
    int mods[ndims];
    // I suspect this 'mods' loop is suboptimal, but it works.
    for (int i = 0; i < ndims; i++)
    {
        int v = size;
        for (int j = 0; j <= i; j++) {
            v /= dims[j];
            mods[i] = v;
        }
    }
    for (int offset = 0; offset < size; offset++)
    {
        printf("%s", "array");
        for (int i = 0; i < ndims; i++)
        {
            int p = offset / mods[i];
            printf("[%d]", p % dims[i]);
        }
        printf(" = %d\n", base[offset]);
    }
}

void B(void)
{
    enum { dim1 = 4, dim2 = 6 };
    int array1[dim1][dim2] =
    {
        {  0,  1,  2,  3,  4,  5 },
        { 22, 21, 20, 19, 18, 17 },
        { 32, 31, 30, 39, 38, 37 },
        { 42, 41, 40, 49, 48, 47 },
    };
    int array2[dim2][dim1][dim2] =
    {
        {
            { 15, 68, 67, 16, 105,  4 },
            { 25, 58, 67, 16, 115,  4 },
            { 35, 48, 67, 16, 125,  4 },
            { 45, 38, 67, 16, 135,  4 },
        },
        {
            { 19, 69, 77, 16, 205,  5 },
            { 29, 59, 77, 16, 215,  5 },
            { 39, 49, 77, 16, 225,  5 },
            { 49, 39, 77, 16, 235,  5 },
        },
        {
            { 12, 64, 87, 16, 305,  6 },
            { 22, 54, 87, 16, 315,  6 },
            { 32, 44, 87, 16, 325,  6 },
            { 42, 34, 87, 16, 335,  6 },
        },
        {
            { 17, 63, 97, 16, 405,  7 },
            { 27, 53, 67, 16, 415,  7 },
            { 37, 43, 97, 16, 425,  7 },
            { 47, 33, 97, 16, 435,  7 },
        },
        {
            { 10, 60, 90, 10, 500, 97 },
            { 20, 50, 60, 20, 510, 87 },
            { 30, 40, 90, 30, 520, 77 },
            { 40, 30, 90, 40, 530, 67 },
        },
        {
            { 11, 63, 97, 36, 605, 39 },
            { 21, 53, 67, 46, 615, 38 },
            { 31, 43, 97, 56, 625, 27 },
            { 41, 33, 97, 66, 635, 26 },
        },
    };
    A(&array1[0][0],    2, dim1, dim2);
    putchar('\n');
    A(&array2[0][0][0], 3, dim2, dim1, dim2);
}

int main(void)
{
    B();
    return(0);
}

示例输出

array[0][0] = 0
array[0][1] = 1
array[0][2] = 2
array[0][3] = 3
array[0][4] = 4
array[0][5] = 5
array[1][0] = 22
array[1][1] = 21
array[1][2] = 20
array[1][3] = 19
array[1][4] = 18
array[1][5] = 17
array[2][0] = 32
array[2][1] = 31
array[2][2] = 30
array[2][3] = 39
array[2][4] = 38
array[2][5] = 37
array[3][0] = 42
array[3][1] = 41
array[3][2] = 40
array[3][3] = 49
array[3][4] = 48
array[3][5] = 47

array[0][0][0] = 15
array[0][0][1] = 68
array[0][0][2] = 67
array[0][0][3] = 16
array[0][0][4] = 105
array[0][0][5] = 4
array[0][1][0] = 25
array[0][1][1] = 58
array[0][1][2] = 67
array[0][1][3] = 16
array[0][1][4] = 115
array[0][1][5] = 4
array[0][2][0] = 35
array[0][2][1] = 48
array[0][2][2] = 67
array[0][2][3] = 16
array[0][2][4] = 125
array[0][2][5] = 4
array[0][3][0] = 45
array[0][3][1] = 38
array[0][3][2] = 67
array[0][3][3] = 16
array[0][3][4] = 135
array[0][3][5] = 4
array[1][0][0] = 19
array[1][0][1] = 69
array[1][0][2] = 77
array[1][0][3] = 16
array[1][0][4] = 205
array[1][0][5] = 5
array[1][1][0] = 29
array[1][1][1] = 59
array[1][1][2] = 77
array[1][1][3] = 16
array[1][1][4] = 215
array[1][1][5] = 5
array[1][2][0] = 39
array[1][2][1] = 49
array[1][2][2] = 77
array[1][2][3] = 16
array[1][2][4] = 225
array[1][2][5] = 5
array[1][3][0] = 49
array[1][3][1] = 39
array[1][3][2] = 77
array[1][3][3] = 16
array[1][3][4] = 235
array[1][3][5] = 5
array[2][0][0] = 12
array[2][0][1] = 64
array[2][0][2] = 87
array[2][0][3] = 16
array[2][0][4] = 305
array[2][0][5] = 6
array[2][1][0] = 22
array[2][1][1] = 54
array[2][1][2] = 87
array[2][1][3] = 16
array[2][1][4] = 315
array[2][1][5] = 6
array[2][2][0] = 32
array[2][2][1] = 44
array[2][2][2] = 87
array[2][2][3] = 16
array[2][2][4] = 325
array[2][2][5] = 6
array[2][3][0] = 42
array[2][3][1] = 34
array[2][3][2] = 87
array[2][3][3] = 16
array[2][3][4] = 335
array[2][3][5] = 6
array[3][0][0] = 17
array[3][0][1] = 63
array[3][0][2] = 97
array[3][0][3] = 16
array[3][0][4] = 405
array[3][0][5] = 7
array[3][1][0] = 27
array[3][1][1] = 53
array[3][1][2] = 67
array[3][1][3] = 16
array[3][1][4] = 415
array[3][1][5] = 7
array[3][2][0] = 37
array[3][2][1] = 43
array[3][2][2] = 97
array[3][2][3] = 16
array[3][2][4] = 425
array[3][2][5] = 7
array[3][3][0] = 47
array[3][3][1] = 33
array[3][3][2] = 97
array[3][3][3] = 16
array[3][3][4] = 435
array[3][3][5] = 7
array[4][0][0] = 10
array[4][0][1] = 60
array[4][0][2] = 90
array[4][0][3] = 10
array[4][0][4] = 500
array[4][0][5] = 97
array[4][1][0] = 20
array[4][1][1] = 50
array[4][1][2] = 60
array[4][1][3] = 20
array[4][1][4] = 510
array[4][1][5] = 87
array[4][2][0] = 30
array[4][2][1] = 40
array[4][2][2] = 90
array[4][2][3] = 30
array[4][2][4] = 520
array[4][2][5] = 77
array[4][3][0] = 40
array[4][3][1] = 30
array[4][3][2] = 90
array[4][3][3] = 40
array[4][3][4] = 530
array[4][3][5] = 67
array[5][0][0] = 11
array[5][0][1] = 63
array[5][0][2] = 97
array[5][0][3] = 36
array[5][0][4] = 605
array[5][0][5] = 39
array[5][1][0] = 21
array[5][1][1] = 53
array[5][1][2] = 67
array[5][1][3] = 46
array[5][1][4] = 615
array[5][1][5] = 38
array[5][2][0] = 31
array[5][2][1] = 43
array[5][2][2] = 97
array[5][2][3] = 56
array[5][2][4] = 625
array[5][2][5] = 27
array[5][3][0] = 41
array[5][3][1] = 33
array[5][3][2] = 97
array[5][3][3] = 66
array[5][3][4] = 635
array[5][3][5] = 26

评论:实际上更容易获得3D情况,然后专注于2D情况,而不是将2D情况正确,然后推广到3D情况。


请注意,此技术适用于任何连续数组(如静态分配的示例)。有一些方法可以动态分配数据不连续的数组,这对这种伪数组不起作用。如果您分配一个指针数组,然后每个指针指向一个整数向量或任何类似的方案,这是一个问题。可以使用双下标表示法访问此类“数组”,但生成的代码与访问真正的多维(连续)数组完全不同。

函数A()中的代码不会处理像这样分配的'数组'(为简洁而省略错误检查),即使初始化循环看起来与常规(连续)的初始化循环相同二维数组:

int **base = malloc(4 * sizeof(*base));
for (int i = 0; i < 4; i++)
    base[i] = malloc(6 * sizeof(*base[i]));

for (int i = 0; i < 4; i++)
{
    for (int j = 0; j < 6; j++)
        base[i][j] = 0;
}

for (int i = 0; i < 4; i++)
    free(base[i]);
free(base);

答案 1 :(得分:0)

无法检查变量参数列表并获取大小,因此您必须传递长度参数。

这是一个可以支持任意维度int数组的递归示例:

#include <stdint.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>

void print_array_v(void *a, int cnt, va_list args) {
    va_list nw;
    int i, j;
    i = va_arg(args, int);
    if(cnt > 1) {
            for(j=0; j != i; ++j) {
                    va_copy(nw, args);
                    printf("[%d %d]\n", cnt-1, j);
                    print_array_v(((int **)a)[j], cnt - 1, nw);
                    va_end(nw);
            }
    } else {
            printf("(%d, %p) ", i, a);
            for(j = 0; j != i; ++j) { printf("%d ", ((int *)a)[j]); }
            printf("\n");
    }
}

void print_array(void *a, int cnt, ...) {
    va_list lst;
    va_start(lst, cnt);        
    print_array_v(a, cnt, lst);
    va_end(lst);
}

以下是一个示例驱动程序:

int main(int argc, char ** argv) {
int i,j,k,l;
l = 0;
int ***a = malloc(2 * sizeof(int **));
for (i=0;i!=2;++i) {
    a[i] = malloc(2 * sizeof(int *));
    for(j=0;j!=2;++j) { 
        a[i][j] = malloc(2 * sizeof(int));
        for(k=0;k!=2;++k) {
            a[i][j][k] = ++l;
            printf("(%d %d %d) %d\n", i, j, k, a[i][j][k]);
        }
    }
}
print_array(a, 3, 2, 2, 2);
return 0;
}