Доступ к массиву Ada: указатель на определенный элемент в массиве, позиция которого динамическая в зависимости от входных параметров. - PullRequest
2 голосов
/ 23 сентября 2010

Я работаю в Ada95, и у меня возникают трудности с поиском указателей.

У меня есть код, который выглядит следующим образом:

type vector is array (1 .. 3) of integer;   
type vector_access is access vector;

my_vec : vector;

procedure test is  
  pointer : vector_access := my_vec'access;  
begin   
  ...  
end;

Сбой компиляции по определениюуказателя, говоря

«Префикс« ACCESS »должен быть либо псевдонимом объекта, либо обозначать подпрограмму с не внутренним соглашением о вызовах» * *Затем я изменяю определение самого вектора на:

my_vec : aliased vector  

Теперь он возвращает ошибку компилятора:

"Ожидаемый тип для X'ACCESS, где X обозначает и обозначаетпредставление объекта, должно быть общего типа доступа "

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

Ответы [ 3 ]

6 голосов
/ 23 сентября 2010

Если вы используете GNAT, сообщение об ошибке после «должно быть общего типа доступа» должно было дать вам решение:

добавить «все» к типу «vector_access», определенному вline ...

, чтобы вы получили:

type Vector_Access is access all Vector;

Использование «all» для обозначения общего типа доступа связано с пулами динамического выделения памятив аде.Если вам не нужны динамические пулы выделения памяти, не беспокойтесь об этом и просто включите «все» в определения типов доступа.

Я не уверен, является ли это частью того, что выищите в конце дня, но вы знаете, что в большинстве случаев типы доступа Ада (указатель) используются для обработки динамически распределенной памяти, верно?

Так что вместо указания my_vec на переменную с псевдонимомвы бы динамически выделяли его:

Pointer_2_Dynamic : vector_access := new Vector;

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

type Dynamic_Vector is array (Natural range <>) of Integer;
type Dynamic_Vector_Access is access Dynamic_Vector;

N : Natural := 10; -- Variable here, but could be a subprogram parameter.
Dyn_Vector : Dynamic_Vector_Access := new Dynamic_Vector(1..N);
5 голосов
/ 24 сентября 2010

OK.Первый урок по Ada для опытных программистов Cish: Параметры Ada отличаются от параметров Cish .В C (параметры предварительной ссылки) каждый отдельный параметр является эквивалентом параметра Ada 'in', с дополнительным условием, что компилятор C всегда должен тупо передавать всю вещь в стеке, независимо от его размера.Так что вы, бедные C-кодеры, забиваете себе в мозг то, что вы никогда не передаете большие объекты напрямую подпрограммам, а всегда используете указатели.

Ада отличается.Вы сообщаете компилятору, как вы хотите получить доступ к своим параметрам (только для чтения - «in», только для записи - «out» или для чтения «write» - «in out»).Однако это не имеет ничего общего с передачей параметров.Механизм передачи параметров зависит от компилятора, и компилятор выберет наиболее эффективный способ сделать это .На практике почти на всех платформах это означает, что все, что слишком велико для регистра, будет передано по ссылке.Но это деталь реализации, а дело компилятора, а не ваше.Вам даже не нужно думать об этом, за исключением действительно редких случаев.

Так что стисните зубы и передайте этот массив голым как параметр in out.Поверьте мне, вам это понравится.

type vector is array (natural range <>) of integer;
my_vec : vector(1..3); 

procedure test (subject : in out vector) is   
begin    
  ...   
end; 

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

Первый довольно небезопасен (опасен нераспределенных указателей и утечек памяти), а второй еще более небезопасен (объекты стека могут выходить из области видимости раньше, чем ваш указатель, и даже если онине одна маленькая ошибка размера может повредить всю вашу программу).В Ada вы можете делать и то, и другое, но в отличие от многих языков, оно разработано для того, чтобы сделать небезопасные вещи требующими немного больше работы с вашей стороны, и сделать очень небезопасные вещи основным написанием PITA.

Например,если бы вы просто динамически выделяли весь массив, вам не пришлось бы дурачиться с этим бизнесом aliased и all.Более того, если вы просто хотите передать массив в подпрограмму, вы можете просто передать его в качестве параметра, и вам даже не придется дурачиться с динамическими распределениями и освобождениями.Опять же, компиляторы Ada достаточно умны, чтобы передавать большие объекты по ссылке (да, даже если вы указали in).Это требует корректировки отношения от кодеров C / C ++, которые привыкли указывать своим тупым компилятору не передавать 10-миллиметровые объекты в стек.Вы должны научиться позволять компилятору Ada беспокоиться о том, как эффективно передавать ваши параметры, и вы можете просто беспокоиться о том, как писать отличный код.

1 голос
/ 23 сентября 2010

Думаю, я нашел это для всех, кто сталкивался с той же проблемой.

Ответ связан с тем, что конкретно называется псевдонимом.Объявление массива должно быть:

type vector is array (1 .. 3) of aliased integer;

, чтобы целые числа сохранялись в памяти, а не в регистрах.

...