Количество элементов внутренних массивов многомерного массива в C - PullRequest
0 голосов
/ 30 июня 2018

Я новичок в C и, читая онлайн, я понимаю, что с помощью sizeof () у меня может быть память, выделенная для него в байтах, и если я разделю ее на элемент внутри или тип данных, я могу иметь количество элементов массива.

Я пытаюсь использовать эту логику с двумерным многомерным массивом, и у меня возникают проблемы с внутренними массивами.

Вот пример кода:

#include <stdio.h>

#define ARRAYLEN(arr) (sizeof(arr) / sizeof(arr[0]))

int main(void) {
    int input[][20] = {
        {90, 1349, 430, 198, 677, 1869, 1692, 1098, 761, 677, 1004 ,0},
        {163, 642 ,2445, 1032, 2738 ,1591 ,3950 ,1600 ,651, 0},
        {1730 ,3067 ,1956, 723 ,1307 ,417 ,2838 ,1486 ,3114 ,3698 ,1881 ,0},
        {2337, 5131 ,1527 ,5042 ,953, 0},
        {80, 389, 413 ,209 ,219, 100 ,191, 419, 181 ,473 ,271 ,0},
        {22 ,3900 ,4057, 439 ,2642, 1447 ,3553, 2244, 3328, 3924, 1486, 400, 2394 ,0},
        {2870, 621 ,3779, 3508, 3729, 2985, 1083, 1384, 3782 ,2606, 637, 0},
        {1400, 108 ,472 ,1411, 10, 453, 1631, 1331, 0},
        {808 ,1584, 2545, 2294, 1983, 842 ,447, 807 ,3711, 1067, 490, 0},
        {435 ,14 ,261, 395, 340, 340, 25, 114, 178 ,52 ,232 ,19, 54, 0},
        {6181 ,2026, 4061, 7796 ,5192 ,958, 4190, 965 ,2642, 5082, 2579, 1872 ,0},
        {2030, 106, 579, 36, 1147 ,111 ,1393 ,459, 209, 1847, 1171, 415, 725, 1245, 0}
    };

    printf("%d", ARRAYLEN(input));
    printf(" ");
    printf("%d", ARRAYLEN(input[0]));

    printf(" ");
    printf("%d", sizeof(input[0]) / sizeof(int));

    return 0;
}

Первый printf() возвращает 12, что верно, а второй printf() (и третий) возвращает 20, то есть память, которую я выделил для него, но не количество элементов, которые есть у каждого из них. Это то, что я ищу, чтобы использовать цикл for.

Может кто-нибудь объяснить, как я могу это сделать? Или что я делаю не так?

Я нигде не могу найти ответ / объяснение.

Заранее спасибо

Ответы [ 3 ]

0 голосов
/ 30 июня 2018

Ваша программа имеет потенциально неопределенное поведение на архитектурах, где sizeof(size_t) != sizeof(int). Либо используйте %zu в строках формата printf, либо приведите аргументы как (int).

Вы также должны заключить в макрос ARRAYLEN аргумент более аккуратно.

Вот модифицированная версия:

#include <stdio.h>

#define ARRAYLEN(arr) (sizeof(arr) / sizeof((arr)[0]))

int main(void) {
    int input[][20] = {
        {90, 1349, 430, 198, 677, 1869, 1692, 1098, 761, 677, 1004 ,0},
        {163, 642 ,2445, 1032, 2738 ,1591 ,3950 ,1600 ,651, 0},
        {1730 ,3067 ,1956, 723 ,1307 ,417 ,2838 ,1486 ,3114 ,3698 ,1881 ,0},
        {2337, 5131 ,1527 ,5042 ,953, 0},
        {80, 389, 413 ,209 ,219, 100 ,191, 419, 181 ,473 ,271 ,0},
        {22 ,3900 ,4057, 439 ,2642, 1447 ,3553, 2244, 3328, 3924, 1486, 400, 2394 ,0},
        {2870, 621 ,3779, 3508, 3729, 2985, 1083, 1384, 3782 ,2606, 637, 0},
        {1400, 108 ,472 ,1411, 10, 453, 1631, 1331, 0},
        {808 ,1584, 2545, 2294, 1983, 842 ,447, 807 ,3711, 1067, 490, 0},
        {435 ,14 ,261, 395, 340, 340, 25, 114, 178 ,52 ,232 ,19, 54, 0},
        {6181 ,2026, 4061, 7796 ,5192 ,958, 4190, 965 ,2642, 5082, 2579, 1872 ,0},
        {2030, 106, 579, 36, 1147 ,111 ,1393 ,459, 209, 1847, 1171, 415, 725, 1245, 0}
    };

    printf("%d %d %d\n",
        (int)ARRAYLEN(input),
        (int)ARRAYLEN(input[0]),
        (int)(sizeof(input[0]) / sizeof(int)));

    return 0;
}

Вывод 12 20 20, как и ожидалось:

  • 12 - количество элементов в массиве input: 12 строк по 20 int.
  • 20 - количество элементов в массиве input[0] согласно определению.
  • 20 - это снова количество элементов в массиве input[0], так как int - это тип его элементов.

Тот факт, что у вас меньше элементов в инициализаторе для некоторых или всех вложенных массивов, не меняет их размер, каждый вложенный массив имеет 20 элементов, как указано в определении int input[][20], а остальные элементы инициализируются как 0. Количество подмассивов определяется компилятором из инициализатора.

0 голосов
/ 30 июня 2018

Ваш вопрос может быть уменьшен до:

int array[10] = {1,2,3};

ARRAYLEN(array) == 10

Если вы явно укажете размер для вашего массива (int x[N] вместо int x[]), то массив всегда будет иметь указанный вами размер, независимо от количества инициализаторов внутри фигурных скобок.

Элементы без инициализаторов инициализируются нулями.

Другими словами, нет разницы между

int array[10] = {1,2,3};

и

int array[10] = {1,2,3,0,0,0,0,0,0,0};

Кроме того, как уже отмечали другие, ваш макрос должен быть определен как

#define ARRAYLEN(arr) (sizeof(arr) / sizeof((arr)[0]))

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

Значение, полученное из этого макроса, должно быть напечатано с помощью %zu, поскольку оно имеет тип size_t, а не int.

0 голосов
/ 30 июня 2018

У вас есть массив из 12 строк по 20 элементов в каждой. Количество строк определяется количеством инициализируемых вами строк. Количество элементов определяется числом 20.

Размер, заданный (sizeof(input) / sizeof(input[0])) - это количество строк.

Размер, заданный (sizeof(input[0]) / sizeof(input[0][0])) - это количество элементов в строке

Размер, заданный (sizeof(input) / sizeof(input[0][0])), представляет собой целое число, то есть строки х столбцов.

Следующий код печатает массив:

for (int i=0; i<ARRAYLEN(input); i++) {
    for (int j=0; j<ARRAYLEN(input[0]); j++) {
        printf("%d ",input[i][j]);
    }
    printf("\n");
}
...