Форум: "Основная";
Текущий архив: 2003.05.15;
Скачать: [xml.tar.bz2];
ВнизVar и const параметры Найти похожие ветки
← →
Asteroid (2003-05-02 20:39) [0]Есть примерно такой код:
type TMatrix = array [ 0..15 ] of Single;
procedure MatrixMult( var q: TMatrix; const a, b: TMatrix );
begin
...
q[ i ] = q[ i ] + a[ j ] + b[ k ];
...
end;
procedure Call()
begin
...
MatrixMult( M, M, M2 ); // т.е. q = a
...
end;
Вопросы такие:
1) значения в массиве q изменяются - будут ли меняться значения в массиве a?
2) что будет, если вместо var использовать out?
3) имеет ли вообще смысл использовать var, out и const для массивов?
← →
jack128 (2003-05-02 21:50) [1]
> 1) значения в массиве q изменяются - будут ли меняться значения
> в массиве a?
А проверить самому?
Сделал тест на строках, все нормально в q изменились занчения, а в а остались те же
> 2) что будет, если вместо var использовать out?
при out переменная обнуляется
> 3) имеет ли вообще смысл использовать var, out и const для
> массивов?
Имеет
← →
Asteroid (2003-05-02 23:06) [2]1) Сделал тест на массивах. Как и предполагал, изменились и в q, и в a :( Заодно нашел выход - достаточно убрать const :)
2) не обнуляется (по крайней мере, массив)
3) thanks
← →
jack128 (2003-05-02 23:47) [3]Странно все это... У тя какая дельфя?
← →
Aleks1 (2003-05-03 02:42) [4]2 jack128 © (02.05.03 23:47)
"Странно все это... "
А странно ли? Насколько помню, утверждение const в списке параметров функции(процедуры) лишь означает обязательство программиста не изменять значение данного параметра внутри функции, посему компиллятор считает себя в праве передать данный параметр по ссылке, а не по значению.
← →
Morfein (2003-05-03 09:06) [5]>> Aleks1:
Хм, как ты представляешь себе передачу массива по значению? :))
ЗаPUSHить в стэк все элементы? :) Или по регистрам сопроцессора распихать? :))
← →
Aldor (2003-05-03 09:40) [6]Когда ты передаешь не переменные, а структуры, будь то классы или массивы, ты передаешь только их указатели (сами массивы в стек не пишуться), поэтому const и var влияют только на то, что ты можешь изменить указатель, а менять данные по ссылке можешь как угодно.
P.S. var и out отличаются тем, что аргумент var ты можешь и читать и изменять, а out - только изменять. Удачи.
← →
Morfein (2003-05-03 10:50) [7]>> Aldor:
Я-то это знаю...
← →
Набережных С. (2003-05-03 14:29) [8]>Aldor © (03.05.03 09:40)
>var и out отличаются тем, что аргумент var ты можешь и читать и изменять, а out - только изменять
Неужели?
← →
evvcom (2003-05-03 23:57) [9]
> Morfein © (03.05.03 09:06)
> >> Aleks1:
> Хм, как ты представляешь себе передачу массива по значению?
> :))
> ЗаPUSHить в стэк все элементы? :) Или по регистрам сопроцессора
> распихать? :))
В этом есть доля истины. В любом случае в стек пихается указатель на массив, но! Если идет передача массива без const, то в вызываемой процедуре/функции во время инициализации отводится в стеке место под такой же массив и копируется туда все содержимое исходного массива, и дальнейшая работа идет с копией, которая впоследствии уничтожается. Если же массив передается как const, то компилятор считает, что массив действительно меняться не будет, и никакой локальной копии этого массива не делается, поэтому ничего странного в том, что массив A изменялся одновременно с Q.
Если кому это кажется неправдоподобным, смотрите CPU Window. Это разрешит все Ваши сомнения.
← →
default (2003-05-04 00:29) [10]параметры-константы - это тоже самое что и параметры-значения разве что
нельзя редактировать их стековые копии(явно)
вот код который по-моему это доказывает
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
TMas = Array[1..3] of Byte;
var
Form1: TForm1;
Mas: TMas = (1, 2, 3);
implementation
{$R *.dfm}
procedure Test(const M: TMas);
begin
PByte(Integer(@M[1]) + 1)^ := 19;
Form1.Caption := IntToStr(M[2]) // Form1.Caption = "19" (меняется значение в стеке)
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Test(Mas);
Caption := Caption + " : " + IntToStr(Mas[2]) // Mas[2] = 2 (глобальный массив не изменился)
end;
end.
если я не прав то скажите(
всякое бывает
← →
evvcom (2003-05-04 02:06) [11]
> default © (04.05.03 00:29)
Браво! Я оказался немного неправ, заявив "В любом случае в стек пихается указатель на массив". Я никогда не использовал ранее массив общим размером до 4 байт. Посмотрел вышеприведенный пример в D5, и действительно выводится результат "19 : 2". Причина: если массив до 4 байт включительно, то (5 дельфи во всяком случае) компилятор все же передает в функцию/процедуру не указатель, а сами данные (смотрел через CPU Window). Увеличьте размер массива хотя бы до 5 байт и получите результат "19 : 19".
Вывод: используйте данные правильно, чтобы избежать кривотолков. Вполне вероятно, что в последующих версиях какие-либо недокументированные возможности/способности утратятся, а на замену появятся (а может и не появятся) другие. Если есть желание изменить переменную, то объявляйте параметр как var, если она точно постоянная, то const. И не надо слишком много мудрить!
← →
default (2003-05-04 12:49) [12]to evvcom
Отличная работа!
так даже не подумаешь что для разных размеров переменных компилятор
действует по разному! Теперь будем знать!
← →
Нуу (2003-05-05 01:37) [13]А если попробовать массив размером 3 байта? Он вроде бы меньше 4-х!
Уже начиная с TurboPascal стандартными размерами являются 1 aka byte, 2 aka word(integer), 4 aka Long.
← →
evvcom (2003-05-05 08:20) [14]
> Нуу (05.05.03 01:37)
> А если попробовать массив размером 3 байта?
Смотри пример default © (04.05.03 00:29)
> TMas = Array[1..3] of Byte;
Это и есть массив в 3 байта. С этого все и началось.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2003.05.15;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.009 c