Указатель на тип массива (пользовательские типы) - PullRequest
0 голосов
/ 04 февраля 2019

У меня есть пользовательский тип массива, определенный в коде, и указатель на этот тип массива, также определенный.Я пытаюсь найти корреляцию между пользовательским типом массива и указателем на пользовательский тип массива.Как мне присвоить значение указателю пользовательского типа массива, чтобы я мог перебирать массив, используя указатель?

#include<stdio.h>

typedef int array_type[3];
typedef array_type* ptr_array_type;

int main() {
   array_type a = {2,3,4};
   ptr_array_type ptr;

   ptr = a;

   printf("%d\n",*ptr);

}

Я знаю, что имя массива содержит указатель на первый элемент.Я получаю недопустимую распечатку: -50204788 вместо 2.

Я также получаю предупреждение:

предупреждение: присваивание 'ptr_array_type' {aka 'int (*) [3]'}из несовместимого типа указателя 'int *' [-Wincompatible-pointer-types] ptr = a;

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

Ответы [ 3 ]

0 голосов
/ 04 февраля 2019

Как назначить значение указателю пользовательского типа массива, чтобы я мог перебирать массив с помощью указателя?

Учитывая array_type, определенное

typedef int array_type[3];

, тип указателя, которому вы можете назначить array_type, равен int *:

typedef int *ptr_array_element;

Вы можете (на вид) назначить объект array_type указателю типа ptr_array_element:

array_type a = {2, 3, 4};
ptr_array_element p = a;

Сделав это, вы можете получить доступ к первому элементу массива с помощью оператора derferencing.

assert(*p == 2);

И вы можете использовать его, как итератор C ++:

printf("%d\n", *p++);
printf("%d\n", *p++);
printf("%d\n", *p++);

НО НЕ.

Используйте typedefs экономно, когда они скрывают нерелевантные детали, существенно улучшают четкость кода или тому подобное.Избегайте использования typedef, которые скрывают релевантные детали, такие как объекты этого типа, являются указателями или массивами, если, возможно, эти детали не являются полностью ясными из имен типов, или если скрытие их не является намеренным и безвредным.Очень редко можно скрыть природу массива или указателя.

0 голосов
/ 04 февраля 2019

ptr_array_type псевдонимы int (*)[3], а не int * - вы не сможете использовать его для перебора array_type.Вы могли бы использовать его для перебора массива из array_type, например:

array_type arr[3];
ptr_array_type ptr = arr;

while ( size_t i = 0; i < 3; i++ )
  do_something_with( ptr[i] );

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

typedef int array_type[3];    // probably want to replace int with another
typedef int *ptr_array_type;  // typedef to abstract out the type
...
array_type a = {1, 2, 3}; // yuck! don't do this! a is not obviously an array,
                          // so an array initializer looks wrong in this context
ptr_my_type p = a;

printf( "%d", *p );

Однако ...

Если вы используете typedef, чтобы абстрагировать детали реализации для типа, то выследует абстрагироваться от всех деталей реализации для этого типа, включая такие вещи, как разыменование и подписка.Вы захотите создать полный API, такой как:

 array_type *arr = new_array_type( 1, 2, 3 );  // even this is leaky since it assumes we know
                                               // the array element type is integral
 array_type_iterator *itr = new_array_type_iterator( arr );
 array_element_type target;

 begin_iterator( &itr ); 
 while( next_iterator( &itr ) )
 {
   get_data_from_iterator( itr, &target );
   write_array_element_to( stdout, target );
 }

 free_array_type_iterator( itr );
 free_array_type( arr );

Частичные или неплотные абстракции просто ведут к коду, который запутывает использование и обслуживание.Если пользователь типа должен знать о «массивности» или «указателе» этого типа, чтобы правильно его использовать, не скрывайте эти качества за определением типа, не предоставляя замены для [] иунарные * операторы.Также предоставьте некоторый способ абстрагирования ввода / вывода - не заставляйте пользователя знать, использовать ли %d или %f или %s в операторе printf, если они не работают с примитивомтип.

0 голосов
/ 04 февраля 2019

ptr - указатель на int[3];a - это и int[3].Хотя мне не нравится typedef тип указателей в целом, если вы настаиваете на этом подходе, вот как вы можете разыменовать первый элемент a из ptr:

ptr = &a;
printf("%d\n", **ptr);
...