Можно ли написать функцию, которая может выгружать произвольный размерный массив int в C? - PullRequest
2 голосов
/ 29 июля 2011

Наконец, если я хочу сбросить массив, просто:

int array[dim1][dim2]..;

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

Возможно ли это в C?

UPDATE

Как определить тип array в A(array, dim1, dim2, dim3, dim4...);, чтобы компилятор не выдавал никаких предупреждений?

Ответы [ 2 ]

5 голосов
/ 29 июля 2011

Да

В вызове 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

Комментарий: на самом деле было проще получить правильное трехмерное изображение, а затем специализироваться на двумерном случае, чем правильно настроить двумерное дело и затем обобщить на трехмерное дело.


Обратите внимание, что этот метод работает для любого смежного массива (например, статически размещенный пример). Существуют способы динамического размещения массивов, в которых данные не являются смежными, и это не будет работать на таких псевдораборах. Это проблема, если вы выделяете массив указателей, и каждый указатель затем указывает на вектор целых чисел или любую аналогичную схему. К таким «массивам» можно обращаться, используя двойную запись, но сгенерированный код сильно отличается от доступа к истинному многомерному (непрерывному) массиву.

Код в функции A() не будет обрабатывать «массив», выделенный так (проверка ошибок для краткости опущена), даже если цикл инициализации выглядит почти так же, как цикл инициализации для обычного (непрерывного) 2D-массива :

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);
0 голосов
/ 29 июля 2011

Нет способа проверить список переменных аргументов и получить размер, поэтому вам нужно передать аргумент длины.

Вот рекурсивный пример, который может поддерживать массив произвольных размерных чисел типа 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...