| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Delphi: Общие вопросы > Открытый массив |
| Автор: Scrip 24.5.2004, 14:38 |
| Можно ли считать открытый массив динамическим массивом предствляющим собой параметр подпрограммы? __________________________________________________________ Что такое конструктор массива и для чего он нужен? |
| Автор: Kesh 24.5.2004, 17:29 |
| Мне вопрос непонятен, поясни, что такое открытый массив?.. Добавлено @ 17:35 Что ты имеешь в виду под конструктором массива? SetLength? |
| Автор: Jey_k 24.5.2004, 22:14 |
| Scrip массивы можно, конечно, передавать как параметры подпрограммы, а что такое открытый массив? Уж не объявленный ли глобально? А динамический массив, насколько мне известно, тот у которого размерность может менятся в нужных случаях. Если все так, то связи в первом предложении не вижу(не обижайся, может не так понял) А конструктор-процедура создания. qwe:array[1..10] of integer; например |
| Автор: p0s0l 25.5.2004, 01:23 | ||||
Открытый массив - массив неизвестного размера. Пример:
Но это не динамический массив. Ответ на вопрос - нет. К примеру, я не смогу в Proc1 написать SetLength(m, 10); Сколько выделил памяти под m, столько и могу использовать... Можно передать дин. массив в качестве открытого массива, также как и статический:
При передаче дин. массива передается указатель на первый элемент данных, и длина дин. массива (которая не известна на этапе компиляции). При передаче стат. массива в качестве открытого массива длина массива сразу известна на этапе компиляции... |
| Автор: p0s0l 25.5.2004, 01:35 | ||
ЗЫ: Насчет статических массивов: можно схитрить насчет длины. Например, для приведенной выше процедуры можно сделать так:
В результате, хоть и размер статического массива = 8, обработке в Proc1 пойдут только первый 6 (5+1=6) элементов... Ну это так, мало ли кому будет лень передавать еще один параметр для указания размера массива... |
| Автор: p0s0l 25.5.2004, 01:47 | ||||||||
Пример:
Тут m - открытый массив. Пример вызова:
Пример использования конструктора:
Думаю, из примера видно что конструктор налету собирает массив. |
| Автор: Unregistered 25.5.2004, 02:16 | ||||||
p0s0l, чего-то не понял.... в приведенном тобой коде, в процедуру передается динамический массив без параметра его длины... А дальше ты пишешь, что надо передавать длину массива. И так ли обязательно передавать длину массива? У меня написана длл в которой реализованы такие функции:
Вызывая первую функцию я передаю ей динамический массив, в CheckCS передаю и динамический массив и открытый массив - SizeOf отлично справляется (как видно нет параметра передающего длину массива). Твой ответ заставил меня задуматься, а правильно ли я это реализовал? Поясни, пожалуйста. PS написано несколько программ с использованием этой длл, и все нормально работает. |
| Автор: p0s0l 25.5.2004, 09:21 |
| Я неправильно выразился. И имел в виду, что длина массива передается неявным параметром, что я потом и показал с помощью "псевдо"-функции... |
| Автор: Scrip 25.5.2004, 13:43 | ||||
Непонятно. Что значит конструктор налету собирает массив? Какой массив? Ведь при выполнении процедуры Proc1 не описано каким фактическим параметром заменить формальный параметр m. |
| Автор: Unregistered 25.5.2004, 13:54 |
| p0s0l, спасибо. С асмом у меня туговато. |
| Автор: p0s0l 25.5.2004, 14:19 | ||||||
Какой массив ? Вот такой: [1,6,4,7,3,4,a,b,c,d] - в квадратных скобках друг за другом перечислены элементы передаваемого массива... Что значит "Налету собирает" ? Конструктор создает в стеке временный массив из перечисленных элементов, и передает указатель на него и длину (но это мы не видим), после завершения вызванной процедуры массива уже не будет... Конструктором можно пользоваться только для передачи параметров. И они не могут передаваться в качестве var-параметров (понятно почему)... Вот два абсолютно эквивалентных примера (даже код в результате генерится одинаковый):
|
| Автор: Scrip 25.5.2004, 14:20 | ||
Если "Открытый массив - массив неизвестного размера", то под m память вообще не выделена. Так? Или ... нет... не так Добавлено @ 14:23 Все, с конструктором разобрался! |
| Автор: p0s0l 25.5.2004, 14:24 | ||
Выделена. Процедура Proc1 на этапе компиляции не знает размер массива. При выполнении же программы она в качестве дополнительного параметра (которого мы не видим) получает размер массива... |
| Автор: Kesh 25.5.2004, 14:30 | ||
Разве?.. Мне казалось, что получив указатель (только его)... Она уже сама определяет размер массива... Я не отрицаю того, что этот размер хранится в программе, но по-моему в процедуру он в заголовке не передается... |
| Автор: p0s0l 25.5.2004, 14:38 |
| Kesh, если я тебе дам только указатель на ячейку памяти, как ты узнаешь сколько массив занимает ? Он может и 10 байт занимать, а может 10 мб... Если я в var'е написал: m : array [0..31] of byte; То m займет ровно 32 байта. В памяти нигде не хранится размер этого массива... |
| Автор: Scrip 25.5.2004, 14:44 |
| p0s0l, а сколько выделена? Намерняка мы этого опять незнаем Размер массива процедуры Proc1 равен фактичекому параметру, заменившему формальный параметр процедуры proc1. Если понял что я сказал ответь пожалста. |
| Автор: p0s0l 25.5.2004, 17:53 |
| Ну вроди типа того... |
| Автор: Kesh 25.5.2004, 20:38 | ||
p0s0l Ну дал ты мне указатель m: array of integer; Ну и что мне мешает сделать так
|
| Автор: p0s0l 25.5.2004, 20:49 |
| Kesh, ну и как же по-твоему прога узнает значение High(m) ? Из космоса бог пошлет что ли ? Как раз этот самый High(m) и передается в качестве неявного невидимого параметра... |
| Автор: Kesh 25.5.2004, 21:00 |
| А ты уверен, что он передается, а не хранится в программе?.. |
| Автор: p0s0l 25.5.2004, 22:23 |
| Kesh, такое ощущение, что ты надо мной издеваешься... В самом начале было сказано, что у открытого массива длина на этапе компиляции неизвестна. Как тогда High(m) может быть известен компилятору, если процедуре могут передать как массив из 10 элементов, так и массив из 1000 элементов ? Где этот High(m) по-твоему может хранится ? Это раз. Во-вторых, тоже, почти в начале же выявил с помощью псевдо-функции неявный параметр, который как раз является High(m)... |
| Автор: Kesh 25.5.2004, 22:34 | ||||||
p0s0l Ничего я над тобой не издеваюсь... Мне в самом деле непонятно...
P.S. Мне действительно интересно... |
| Автор: p0s0l 27.5.2004, 18:32 | ||||||||||
Гм... Пример:
Два массива разной длины начинаются с одного и того же адреса (накладываются друг на друга). В обоих вызовах Proc1 мы передаём указатель на одну и ту же ячейку памяти... И как процедура Proc1 определит, длину какого массива ей использовать: a и b ? Ведь по твоей гипотезе ей передается только указатель... Так что тут облом будет...
Ну если не веришь - проверь сам. Набери чуть выше приведенный пример. В дебаггере глянь на вызовы Proc1:
lea eax, [ebp-$28] в обоих вызовах загружает в eax один и тот же адрес - начало массива a (или массива b, т.к. они наложены друг на друга). Далее в edx засовывается макс. элемент массива (тот самый High(m)). Далее идет вызов Proc1... |
| Автор: Kesh 27.5.2004, 23:31 | ||||||||
И что по-твоему означает call @DynArrayHigh Добавлено @ 23:36 Оно же засовывает High(m) в edx... a в Proc1 передается eax... Мне вот интересно... Ведь Proc1 берет значение из edx сама... Этот самый High берется из программы... |
| Автор: Girder 28.5.2004, 00:16 |
| Как не напиши: procedure Proc1(var m : array of integer); или procedure Proc1(m : array of integer); в Proc1 - передается указатель на массив и не явно максимальный номер массима. Если напишим: var XXX: array [1..2] of .. begin ... Proc1(xxx); ... end; то в Proc1 - длина массива без проблемм опредилится. А если напишим: Type TXXXP:array of ... var XXX: array of .. XXXP:^TXXXP; n:array of .. T:TList; begin SetLength(XXX,...) ... Proc1(xxx); ... n:=xxx; SetLength(n,...) ... Proc1(n); ... T:=TList.Create; New(XXXP); XXXP^:=n; T.ADD(XXXP); ... XXX:=T.Items[...]; ... Proc1(xxx); ... end; то в Proc1 - при определении длины массива случаются осечки. По этому лудше всегда дополнительно указывать явно максимальное значение массива, т.е: procedure Proc1(var m : array of integer;IMax:integer); |
| Автор: p0s0l 28.5.2004, 01:04 | ||||||||||
| Kesh, ты хоть представляешь о чем речь идёт ? Я тебе об одном, а ты оказывается совсем о другом... Я сказал, что при передаче массива в качестве отрытого массива процедуре Proc1 передаётся: 1) Адрес начала данных 2) № макс. элемента массива (High(m)) (неявно) И далее дискуссия шла именно об этом. Я тебе привел пример со статическим массивом. А ты - с динамическим:
Как видишь, DynArrayHigh вызывается перед вызовом Proc1, а не в самой Proc1. Далее идёт:
А edx КУДА передаётся ??? Он идёт туда же в Proc1, и если в процедуре Proc1 встретится High(m), то будет использоваться значение edx. Как ни крути, но ты сам щас доказал, что передается адрес массива (eax) и длина массива (edx)... Я так понял, ты пытаешься доказать, что длина динамического массива хранится где-то в ОП. Зачем мне это доказывать ? Я и так с тобой бы согласился... Но длина статического массива всё же нигде не хранится... Girder, если вместо
то всё ок будет, т.к. ты пытался сделать что-то не очень понятное (указатель присвоить массиву, в итоге компилятор решил вообще ничего не делать с xxx). Или же так:
|
| Автор: Girder 28.5.2004, 03:04 | ||
Это и имелось в виду! Просто ошибся. И я не спорю с тобой, а стараюсь разъяснить. Когда то я тоже писал вот-так: -procedure Proc1(var m : array of ...); или(кто как хочет пускай и пишит) -procedure Proc1(m : array of ...); Но в один прекрасный момент сталкнулся с проблеммой не правильного определения размера массива в Не спорю - это могло произойти только на моем компьютере, в данном версии компилятора, в это утро, при этом расположении планет и т.п. хрень - но это произошло(а за много лет программирования в Delphi не первый раз сталкнулся с этой проблеммой) |
| Автор: p0s0l 28.5.2004, 03:14 | ||||
Странно это. Тем более что было сказано, что не в вызываемой процедуре определяется размер массива, а в вызывающей... Всё равно, интересно было бы взгянуть на это, но это, как понимаю, единственный случай, и его теперь не воссоздать. Но суть не в этом. Эта проблема не открытого массива, а твоя проблема. Или проблема TList'а, или чего там использовал. Ведь в твоем примере, если сделать так:
И тут бы всплыла точно та же проблема у тебя. Без всяких передач массива в другую процедуру. Потому что ошибка определения длины происходит тут, а не там (в вызываемой процедуре). (В данном случае вообще ошибки не происходит, просто делается не то что хотелось...) |
| Автор: Girder 28.5.2004, 03:24 | ||||||
О... с этим я сталкнулся еще раньше.
Ни чё, зато заставляет быть более предусмотрительным при написании программы.
Не единственный, но ты прав сейчас не воссоздам. А эксперементировать лень, да и некогда(хотя по моему это одно и тоже). Но если вдруг(обещенного три года ждут) - вышлю. |
| Автор: p0s0l 28.5.2004, 03:37 | ||
Я говорил, что странно то, что у тебя размер неправильно определялся в вызываемой процедуре. Хотя определяется-то он в вызывающей... Ну да ладно... Всё равно без багов никуда. Хотя многие баги при ближайшем рассмотрении оказываются и не багами... |
| Автор: Girder 28.5.2004, 04:05 | ||||
Абсолютно верно! Кто с этим спорит! см.выше:
|
| Автор: Kesh 27.5.2004, 19:56 |
| p0s0l Да ничего я не пытался тебе доказать... Мне просто интересно стало... Вот торкнуло меня на передачу параметров и все тут... Сейчас вот действительно склоняюсь к твоим словам... Просто до послееднего момента у меня была мысль, что параметр для edx, тот который @DynArrayHigh, cоздается в самой программе при инициализации, а там уже хранится как переменная... Переубедил... Респект... |