Как делает массив указателей на работу указателей?

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

Итак, где ваша карта по умолчанию будет

Mapper.Map<Domain.User, UsersDetailsViewModel>();

, существует свободный синтаксис для определения более сложных отображений:

Mapper.Map<Domain.User, UsersDetailsViewModel>()
      .ForMember(vm=>vm.UserName, m=>m.MapFrom(u=>(u.UserName != null) 
                                               ? u.UserName 
                                               : "User" + u.ID.ToString()));

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

Если вам требуется более сложное отображение (например, отображение CurrentUser), вы можете создать класс, который реализует интерфейс IResolver, включить логику отображения в эти новые предложения, а затем добавить это в отображение.

Mapper.Map<Domain.User, UsersDetailsViewModel>()
  .ForMember(vm=>vm.IsUserMatch, m=>m.ResolveUsing<MatchingUserResolver>()));

Когда Mapper придет, чтобы сделать отображение, он вызовет ваш пользовательский преобразователь.

Как только вы обнаружите синтаксис метода .ForMember, все остальные виды слотов встанут на свои места.

6
задан T.T.T. 19 June 2009 в 01:02
поделиться

5 ответов

Эта структура

char **Data[70]={NULL};

представляет собой массив из 70 указателей на указатели на char. Компилятор выделяет 70 * sizeof (char **) байтов для этого массива, что предполагает, что 32-битные указатели составляют 280 байтов.

Если вы внутренне думаете об «указателе на char» как о строке, что неверно, но достаточно близко, тогда это массив из 70 указателей на строки. Чтобы создать некое искусство ASCII и представить, что вы распределили и заполнили некоторые значения ....

 Array of        One or more
 char **           char *
+---------+     +---------+
|    0    | --> |   ptr   | -->  "Hello, world"
+---------+     +---------+
|    1    |
+---------+       +---------+
|    2    | ----> |  ptr2   | -->  "Goodbye, cruel world"
+---------+       +---------+
|    3    |
+---------+         +---------+
|    4    | ------> | ptr3[0] | -->  "Message 0"
+---------+         +---------+
    ...             | ptr3[1] | -->  "Message 1"
+---------+         +---------+
|   69    |         | ptr3[2] | -->  "Message 2"
+---------+         +---------+

Вы можете сделать это с помощью такого кода (проверка ошибок, возвращаемых значениями malloc, пропущены):

char **Data[70]={NULL};
char **ptr, **ptr2, **ptr3;

ptr = (char **) malloc(sizeof(char *));
*ptr = "Hello, world";
Data[0] = ptr;

ptr2 = (char **) malloc(sizeof(char *));
*ptr2 = "Goodbye, cruel world";
Data[2] = ptr2;

ptr3 = (char **) malloc(10 * sizeof(char *));
Data[4] = ptr3;

ptr3[0] = "Message 0";
ptr3[1] = "Message 1";
 ...
ptr3[9] = "Message 9"; 

printf("%s\n", *Data[0]);
printf("%s\n", Data[2][0]);
printf("%s\n", Data[4][0]);
printf("%s\n", Data[4][1]);
      ...
printf("%s\n", Data[4][9]);

Подумайте об этом так: каждое запись в массиве - это char ** . Каждая запись может указывать на произвольную ячейку в памяти, указанная ячейка (я) является char * и, таким образом, может указывать на массив символов с нулевым символом в конце, также известный как «строка».

Внимательно обратите внимание на различие между этим и тем, что вы получаете, когда выделяете 2D-массив:

char *Data2[10][70]={NULL};

Выделение Data2 выше дает вам двумерный массив char * указатели, причем упомянутый двумерный массив выделяется в одном фрагменте памяти ( 10 * 70 * sizeof (char *) байтов, или 2800 байтов с 32-битными указателями). У вас нет возможности назначать указатели char ** произвольным местам в памяти, которые у вас есть с одномерным массивом указателей char ** .

Также обратите внимание (с учетом вышеупомянутых объявлений Data и Data2 ), что компилятор будет генерировать другой код для следующих ссылок на массивы:

Data[0][0]
Data2[0][0]

Вот другой способ подумать об этом : Представьте себе что у вас есть несколько массивов указателей на строки:

char *table0[] = { "Tree", "Bench", "Stream" };
char *table1[] = { "Cow", "Dog", "Cat" };
char *table2[] = { "Banana", "Carrot", "Broccoli" };
char **Data[3];

Data[0] = table0;
Data[1] = table1;
Data[2] = table2;

У вас есть массив указателей на «массив указателей на char». Если вы теперь напечатаете значение data [1] [1] , представьте себе это так: data [1] возвращает вам указатель на массив table1 . Тогда значение table1 [1] равно «Собака» .

24
ответ дан 8 December 2019 в 03:40
поделиться

Немного сложно придумать практическое использование массива char **. Особенно с 70 элементами.

Однако предположим, что я собираюсь запустить 70 программ. Как вы, вероятно, знаете, программные аргументы обычно передаются как параметр char ** argv в main () (или char * [] argv , который в подпись функции то же самое). Поэтому, если бы я хотел сохранить указатели argv для всех этих программ, я бы использовал массив, подобный Data . Очевидно, мне также понадобится немного памяти в другом месте, чтобы занимать фактические массивы строк и argv, но это только начало.

Инициализация массива с помощью {NULL} устанавливает все его элементы в NULL. Это полезное сокращение: вы можете инициализировать массив с помощью {firstelement, seconddelement, ...} , но если вы не предоставите достаточно терминов, все остальные будут рассматриваться как 0.

Как и любой другой массив указателей, инициализированный с помощью {NULL}, в памяти это выглядит как 70 указателей NULL, расположенных в ряд. (Обычно) нет разницы в памяти между char ** и любым другим указателем на объект. Я думаю, что это законно написать странную реализацию, в которой есть разница, но не задерживайте дыхание, ожидая ее появления.

Итак, разница между 70 NULL char ** в a row и 70 NULL char * в строке - это то, что было бы на другом конце указателя, если бы они не были NULL. На другом конце char ** находится указатель на char. На другом конце char * находится char. Либо указатель, либо символ может быть первым в массиве,

2
ответ дан 8 December 2019 в 03:40
поделиться

Это не очень очевидно:

char **Data[70]={NULL};

, но с альтернативным объявлением, например:

char* Data[2][3] = {
  {"Nick", "Tom", "Helen"},
  {"one", "two", "three"}
};

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

Изменить: Я использовал Data [2] [3], чтобы показать, что это двумерный массив. Я использовал фиксированный размер для таких размеров, как 2 и 3, просто для демонстрации. Конечно, у нас могут быть:

char* Data[][3]={
  {"Nick", "Tom", "Helen"},
  {"one", "two", "three"},
  // ...
};

или char ** Data []

Хорошо, вот что я имею в виду под двумерным массивом:

char** Data[2]={0};

void test()
{
  char* d1[] = {"1", "2"};
  char* d2[] = {"10", "20", "30"};
  Data[0] = d1;
  Data[1] = d2;

  printf("%s\n", Data[0][0]);
  printf("%s\n", Data[0][1]);
  printf("%s\n", Data[1][0]);
  printf("%s\n", Data[1][1]);
  printf("%s\n", Data[1][2]);
}
1
ответ дан 8 December 2019 в 03:40
поделиться

У вас есть массив из 70 указателей, каждый из которых указывает на другой указатель, каждый из этих указателей указывает на символ. Интересно отметить, что сами массивы являются указателями, поэтому имеется три уровня указателей.

1
ответ дан 8 December 2019 в 03:40
поделиться

Фактически, это указатель на указатель на указатели. Однако, поскольку «указатель» - это не что иное, как место в памяти, на самом деле нет особого смысла делать это, просто делая char * Data [70], кроме как сделать очевидным, что каждый char * является указателем на другой char. * вместо указателя на char.

0
ответ дан 8 December 2019 в 03:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: