Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2003.05.15;
Скачать: CL | DM;

Вниз

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;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.012 c
3-46593
ЧК
2003-04-23 13:23
2003.05.15
Кто может ... UpdateSql


1-46686
Serg!
2003-05-03 19:04
2003.05.15
Куда деваются символы?


7-47025
SetVer
2003-03-20 14:20
2003.05.15
Как узнать имя пользователя (UserName) Windows?


1-46785
XAOC
2003-05-01 18:50
2003.05.15
Иначально скрытая форма


4-47058
fagot
2003-03-14 10:23
2003.05.15
Как вывести текст в окно другого приложения