Как вы создаете массив указателей в C? - PullRequest
0 голосов
/ 25 апреля 2018

Как мне создать массив указателей, где каждый элемент содержит указатель на какое-то другое значение

Например, если у меня есть

int** arr[5] = {0xbfjeabfbfe,0x...}; //is it the right way to do it?

А что значит иметь тип массива void? как void **newArray[5];

И скажем, я хочу динамически распределять память для массива указателей, используя malloc или calloc !! Какой будет синтаксис?

Ответы [ 3 ]

0 голосов
/ 25 апреля 2018

Как создать массив указателей, где каждый элемент содержит указатель на какое-то другое значение

Массив массивов может быть представлен в виде трехмерной матрицы

int*** arr;    // Points to an array of arrays (3 Dimensions)
int** arr[0];  // Points to an array           (2 Dimensions)
int* arr[0][0];// Points to a single element   (1 Dimension)

Если вы знаете размер заранее, вы можете инициализировать трехмерный массив следующим образом:

int arr[2][2][2] = {
   { {1, 2}, {3, 4} },
   { {5, 6}, {7, 8} },
}

Но он не очень читабелен для нетривиальных n-мерных массивов.Другой подход заключается в циклическом обходе каждого измерения.

int*** arr;
int dimensions = 10;

arr = malloc(dimensions * sizeof(int**)); // Allocate an array of 2D arrays

for (int i = 0; i < dimensions; i++) {
  arr[i] = malloc(dimensions * sizeof(int*)); // Allocate an array of arrays 

  for (int j = 0; j < dimensions; j++) {
      arr[i][j] = malloc(dimensions * sizeof(int)); // Allocate array

      for (int k = 0; k < dimensions; k++) {
          arr[i][j][k] = 0; // Fill each element with 0's
      }
  }
}

Этот подход также позволяет динамически распределять массивы.

И что значит иметь тип массива void?like void ** newArray [5];

void* - указатель на неизвестный тип.Если int* означает указатель на int, void* означает указатель на значение, тип которого неизвестен.

0 голосов
/ 25 апреля 2018

Как создать массив указателей в C?

Чтобы создать массив указателей в C, у вас есть одна опция, которую вы объявляете:

  type *array[CONST];  /* create CONST number of pointers to type */

С C99 + вы можете создать массив переменной длины (VLA) указателей, например,

  type *array[var];   /* create var number of pointers to type */

Стандарт определяет оба в C11 Standard -6.7.6.2 Объявление массивов и обсуждение подписки в C11 Standard - 6.5.2.1 Подписка на массив .

Краткий пример использования массива указателей, присвоения указателя каждой строке в2D-массив на массив указателей на int, например,

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

#define COL 3
#define MAX 5

int main (void) {

    int arr2d[MAX][COL] = {{ 0 }},  /* simple 2D array */
        *arr[MAX] = { NULL },       /* 5 pointers to int */
        i, j, v = 0;

    for (i = 0; i < MAX; i++) {     /* fill 2D array */
        for (j = 0; j < COL; j++)
            arr2d[i][j] = v++;
        arr[i] = arr2d[i];          /* assing row-pointer to arr */
    }

    for (i = 0; i < MAX; i++) {     /* for each pointer */
        for (j = 0; j < COL; j++)   /* output COL ints */
            printf (" %4d", arr[i][j]);
        putchar ('\n');
    }
}

Пример использования / Вывод

$ ./bin/array_ptr2int_vla
    0    1    2
    3    4    5
    6    7    8
    9   10   11
   12   13   14

Другим фундаментальным для C является указатель на указатель , но это не «массив», хотя обычно он называется «динамическим массивом» и может быть выделен и проиндексирован для имитации массива.Различие между «массивом» и набором указателей заключается в том, что в массиве все значения гарантированно являются последовательными в памяти - такой гарантии нет с набором указателей и мест памяти, на которые они ссылаются.

Так что же int **arr[CONST] объявляет?

В своем вопросе вы ставите объявление int** arr[5] = {0xbfjeabfbfe,0x...};, так что же это объявляет?Вы заявляете Пять из чего-то, но что?Вы объявляете пять указатель на указатель на int .Вы можете сделать это?Конечно.

Итак, что вы делаете с указатель на указатель на что-то ?Указатель на poitner формирует основу динамически распределенной и перераспределенной коллекции типов.Их обычно называют «динамически распределенными массивами», но это несколько неверно, потому что нет никакой гарантии, что все значения будут последовательными в памяти.Вы объявите определенное количество указателей на каждый int** в массиве.Вам не нужно выделять равное количество указателей.

( примечание: нет никакой гарантии, что память, на которую указывают указатели, будет даже последовательной, хотя сами указатели будут - убедитесь, что вы понимаете это различие и что такое "Массив "гарантирует, а что нет указателей)

int** arr[5] объявляет пять int**.Затем вы можете назначить любой адрес, который вам нравится, каждому из пяти указателей, при условии, что тип int**.Например, вы будете назначать указателям что-то похожее на:

  arr[i] = calloc (ROW, sizeof *arr[i]);  /* allocates ROW number of pointers */

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

  arr[i][j] = calloc (COL, sizeof *arr[i][j]); /* allocates COL ints */

Затем вы можете циклически перебирать целые числа, присваивая значения:

  arr[i][j][k] = v++;

Краткий пример, использующий ваше распределение типов int** arr[5], может быть похож на:

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

#define ROW 3
#define COL ROW
#define MAX 5

int main (void) {

    int **arr[MAX] = { NULL },  /* 5 pointer-to-pointer-to-int */
        i, j, k, v = 0;

    for (i = 0; i < MAX; i++) { /* allocate ROW pointers to each */
        if ((arr[i] = calloc (ROW, sizeof *arr[i])) == NULL) {
            perror ("calloc - pointers");
            return 1;
        }
        for (j = 0; j < ROW; j++) { /* allocate COL ints each pointer */
            if ((arr[i][j] = calloc (COL, sizeof *arr[i][j])) == NULL) {
                perror ("calloc - integers");
                return 1;
            }
            for (k = 0; k < COL; k++)   /* assign values to ints */
                arr[i][j][k] = v++;
        }
    }

    for (i = 0; i < MAX; i++) { /* output each pointer-to-pointer to int */
        printf ("pointer-to-pointer-to-int: %d\n\n", i);
        for (j = 0; j < ROW; j++) {     /* for each allocated pointer */
            for (k = 0; k < COL; k++)   /* output COL ints */
                printf ("  %4d", arr[i][j][k]);
            free (arr[i][j]);   /* free the ints */
            putchar ('\n');
        }
        free (arr[i]);      /* free the pointer */
        putchar ('\n');
    }

    return 0;
}

Вы выделили дляиз пяти смоделированных двумерных массивов, присваивающих каждому массиву указатель int **arr[5], получится:

Пример использования / Вывод

$ ./bin/array_ptr2ptr2int
pointer-to-pointer-to-int: 0

     0     1     2
     3     4     5
     6     7     8

pointer-to-pointer-to-int: 1

     9    10    11
    12    13    14
    15    16    17

pointer-to-pointer-to-int: 2

    18    19    20
    21    22    23
    24    25    26

pointer-to-pointer-to-int: 3

    27    28    29
    30    31    32
    33    34    35

pointer-to-pointer-to-int: 4

    36    37    38
    39    40    41
    42    43    44

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

0 голосов
/ 25 апреля 2018

Массив указателей на целые числа;

int x = 1;
int y = 42;
int z = 12;

int * array[3];

array[0] = &x;
array[1] = &y;
array[2] = &z;

альтернативный синтаксис

int * array[] = {&x,&y,&z};

, что делает его простым.Работайте оттуда

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...