-
Коллеги! 1. Рассмотрим пример: procedure Test(const A: array of Integer);
begin
end;
function Int(): Integer;
begin
end;
var
I: Integer;
begin
Test(1); Test(Int); Test(I); end;
2. Строка Test(I) прекрасно компилируется. Более того, в справке сказано, что это должно компилироваться. http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Parameters_(Delphi)#Open_Array_Parameters Фраза: Instead of an array, you can pass a variable of the open array parameter's base type. It will be treated as an array of length 1.Т.е. это не фича, а сознательно заложенное поведение. 3. Собственно загадка. Как вы думаете, почему сделано именно так: почему можно только переменную, но нельзя результат функции? Или даже константу?!! Где логика? Полагаю, что могут пролить на это свет те, кто имел опыт конструирования своих языков... Я так и не допер((( ЗЫ Delphi 2007.
-
У меня так собралось:
Test(Integer(1)); Test(Int); Test(I);
Test(1); - здесь "1", видимо, не integer.
-
Действительно непонятно. Когда я конструировал свои языки - всё было строго, если функция ожидает число - она получает число, если ожидает массив - она получает массив. А если она ожидает или массив или число, то всё равно каким образом это число или массив получены.
-
Тут надо ставить вопрос не почему именно так, а зачем вообще это преобразование?
-
Константа 1 и результат функции Int адресов не имеют. Переменная I адрес имеет - он и передается в Test.
-
Кроме того, просто 1 - это тип byte. А Integer(1) - это тип Integer.
Можно предположить, что во втором случае заводится временная переменная, адрес которой и передается в Test - поэтому в [1] и собралось.
Но это лишь предположение, а надо смотреть машкод.
-
> DayGaykin © (18.05.17 17:33) [1] > У меня так собралось: > Test(Integer(1));
В D2007 не собирается. Проверял.
> Юрий Зотов © (18.05.17 18:35) [4] > Константа 1 и результат функции Int адресов не имеют.
Юр, не пойдёть)) Если Integer заменить на String, то тоже не будет собираться. Хотя результат Int (теперь после замены это тип String) все равно передается через неявную локальную переменную. Т.е. машкод почти идентичен для [2] и [3]...
-
>Тимохов Дима © (18.05.17 20:29) [6]
Убери слово const из заголовка Test - будет собираться?
-
> Юрий Зотов © (18.05.17 20:43) [7] > >Тимохов Дима © (18.05.17 20:29) [6] > Убери слово const из заголовка Test - будет собираться?
Неа. Пробовал))
ЗЫ Собстно, почему мне интересно докопаться. Знакомо чувство, когда тебя просят что-то доделать: добавь в ЭТО место функционал, который есть в ТОМ месте - ведь ЭТО место и ТО место суть одно и тоже почти! Это же так просто! А ты то как разраб знаешь, что это не фига не одно и то же. Т.е. хочется почувствовать себя на месте заказчика, который хочет разобраться, в чем проблемы у разрабов)) Вот почему, эти ребята из Борланда не сделали такую очевидную вещь: с переменной можно, а с функцией ни-ни!!! Интерес вряд-ли имеет практический смысл. Но интересно же!
-
Да нету тут логики.
-
Тимохов Дима © (18.05.17 20:49) [8]
> Вот почему, эти ребята из Борланда не сделали такую очевидную > вещь: с переменной можно, а с функцией ни-ни!!! Интерес > вряд-ли имеет практический смысл. Но интересно же!
Посмотри генерируемый код, удовлетвори свой интерес. Всегда удивляюсь людям, которым процесс важнее результата.
-
> > В D2007 не собирается. Проверял. >
Написано object pascal, я прочёл free pascal, в нем и проверил.
-
> 3. Собственно загадка. Как вы думаете, почему сделано именно > так: почему можно только переменную, но нельзя результат > функции? Или даже константу?!! Где логика? Логика начинается и тут : > Убери слово const из заголовка Test - будет собираться?- const в этом случаи имеет значение внутри, а снаружи - вызывающий и так и так передаёт адрес и тут: > Более того, в справке сказано, что это должно компилироваться. ...- чтобы ускорить передачу массива если в нём только один элемент, - используя адрес на сам параметр а не на его дубль на стеке Test(i);
0041D564 B8A4584200 mov eax,$004258a4
0041D569 33D2 xor edx,edx
0041D56B E814DAFFFF call Test(int [4294967295],int)
Test([i]);
0041D570 A1A4584200 mov eax,[$004258a4]
0041D575 8945E8 mov [ebp-$18],eax
0041D578 8D45E8 lea eax,[ebp-$18]
0041D57B 33D2 xor edx,edx
0041D57D E802DAFFFF call Test(int [4294967295],int)
Test([i,Int,1]);
0041D582 A1A4584200 mov eax,[$004258a4]
0041D587 8945DC mov [ebp-$24],eax 0041D58A E84DDAFFFF call Project1::Int()
0041D58F 8945E0 mov [ebp-$20],eax 0041D592 C745E401000000 mov [ebp-$1c],$00000001 0041D599 8D45DC lea eax,[ebp-$24] 0041D59C BA02000000 mov edx,$00000002
0041D5A1 E8DED9FFFF call Test(int [4294967295],int) P.S. Зачем программист пишет 'Array' а потом осознанно опускает '[]' я тоже не понял )
-
10.1 Berlin. Компиляция с разными сигнатурами Test.
procedure Test(const A: array of Integer); begin end;
function Int(): Integer; begin Result := 1; end;
var I: Integer;
begin // Test(1); // Всегда ошибка // Test(Integer(1)); // Всегда ошибка // Test(Int); // Ошибка только при var Test(I); // Всегда без ошибок end.
-
> Компиляция с разными сигнатурами Test
Имелись в виду 3 варианта:
procedure Test(const A: array of Integer); procedure Test(var A: array of Integer); procedure Test(A: array of Integer);
-
Так всё компилируется:
Test([1]); Test([Int]); Test([I]);
а это:
Test(I)
я бы для единообразия запретил
-
> Дмитрий Белькевич © (19.05.17 12:28) [15] > Так всё компилируется: > > ? > 1 > 2 > 3 > Test([1]); > Test([Int]); > Test([I]); >
Выглядит как синтаксический мусор.
-
> Выглядит как синтаксический мусор. >
Всё просто - не требуйте на вход массив, не будет мусора. А если требуете - то будьте добры его описать.
-
Коллеги, спасибо за внимание к топику!
Надеялся, что столпы ассемблера и опкода скажут свое веское: сделано так, т.к. только так можно генерить код и никак иначе. Собственно, интерес у меня был больше умозрительный.
Пока в своих версиях остановился на том, что когда-то давно ребята косякнули в синтаксическом анализаторе и пропустили Text(I). А потом побоялись убирать в целях обеспечения обратной совместимости.
-
Тимохов Дима © (19.05.17 23:18) [18]
Жаль, что так и не удалось услышать начальника транспортного цеха.
|