Модераторы: Poseidon, Snowy, bems, MetalFan

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Работа с типами данных, Single и array [0..3] of byte 
:(
    Опции темы
unreg
Дата 29.11.2004, 03:55 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Столкнулся вот с такой интересной штукой: нужно читать данные из файла, у меня есть описание формата этого файла. Первая структура которая в него пишется выглядит примерно так:

имя тип длина
----------------------------
time time_t 4 байта
Vmax int 2 байта
Smax int 2 байта
FR float 4 байта
(типы данных из Си)

по этому описанию я создал свою структуру:

TStruct = record
time: cardinal;
Vmax:word;
Smax:word;
FR: single; (потому, что этот тип занимает 4 байта и представляет число с плавающей точкой)

далее через TFileStream считываю эту структуру. Первые три поля заполняются правильными значениями, а последнее совсем не тем чем надо. Тогда вместо Single ставлю array [0..3] of byte и опять считываю. далее, значение поля FR преобразую так: AValue:=Single(Struct.FR) и получаю правильное значение. Как это объяснить? Почему я не могу сразу считать в переменную типа Single и мне нужно действовать через массив?



  Вверх
~FoX~
Дата 29.11.2004, 09:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


НЕ рыжий!!!
****


Профиль
Группа: Участник Клуба
Сообщений: 2819
Регистрация: 8.10.2003
Где: Зеленоград

Репутация: 13
Всего: 68



Single весит 2 байта.
Используй Real.

Добавлено @ 09:57
Заранее извеняюсь. мог и напутать


--------------------
user posted image
…множественность никогда не следует полагать без необходимости…
PM MAIL WWW ICQ Jabber   Вверх
Guest
Дата 29.11.2004, 10:52 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Цитата
Заранее извеняюсь. мог и напутать

Что, собственно, и сделал. :-)

  Вверх
p0s0l
Дата 29.11.2004, 14:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Г-н Посол
****


Профиль
Группа: Экс. модератор
Сообщений: 3668
Регистрация: 13.7.2003
Где: 58°38' с.ш. 4 9°41' в.д.

Репутация: 58
Всего: 112



Попробуй писать не record, а packed record...

ЗЫ: позже, посмотрев еще раз вопрос, понял, что дело не в выравнивании... smile
Тут и так всё выравнено...

Это сообщение отредактировал(а) p0s0l - 29.11.2004, 16:37


--------------------
С уважением, г-н Посол.
PM   Вверх
_hunter
Дата 30.11.2004, 13:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 8564
Регистрация: 24.6.2003
Где: Europe::Ukraine:: Kiev

Репутация: 15
Всего: 98



Цитата
а последнее совсем не тем чем надо

ну и показал бы чем оно заполняется ( желательно в bin ) и чем должно


--------------------
Tempora mutantur, et nos mutamur in illis...
PM ICQ   Вверх
dm9
Дата 30.11.2004, 14:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дмитрий Копытин
****


Профиль
Группа: Vingrad developer
Сообщений: 3876
Регистрация: 22.7.2002
Где: Москва

Репутация: 6
Всего: 137



Извини, что немного не в тему, но, кажется, к сишному типу int будет ближе smallint, а не word smile Если не unsigned, конечно.
PM MAIL ICQ   Вверх
_hunter
Дата 30.11.2004, 14:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 8564
Регистрация: 24.6.2003
Где: Europe::Ukraine:: Kiev

Репутация: 15
Всего: 98



с какой это радости ( или под какую ось/компилятор )?
из справки:
Цитата

Delphi Size/Values C++ implementation
SmallInt 16-bit integer short
Integer 32-bit integer int



--------------------
Tempora mutantur, et nos mutamur in illis...
PM ICQ   Вверх
dm9
Дата 30.11.2004, 14:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дмитрий Копытин
****


Профиль
Группа: Vingrad developer
Сообщений: 3876
Регистрация: 22.7.2002
Где: Москва

Репутация: 6
Всего: 137



_hunter, конечно, могу что-то не понимать, но сказано было, что сишный int занимает 2 байта:

Цитата(unreg @ 29.11.2004, 03:55)
Vmax int 2 байта
Smax int 2 байта


Я уточнил, что если это так, и int этот не unsigned, то правильнее использовать SmallInt, а не Word.

А под какой компилятор? Ну, под Borland C++ 3.1, например... Под ДОС. 32-разрядные версии уже будут использовать 4-байтный int (опять-таки, насколько я знаю), там надо брать Integer или LongWord в случае беззнакового числа.

Это сообщение отредактировал(а) dm9 - 30.11.2004, 14:55
PM MAIL ICQ   Вверх
unreg
Дата 1.12.2004, 08:02 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Я выбрал word потому, что отрицательных значений эти параметры не могут принимать физически. Так же они не могут принимать значения выше верхнего предела SmallInt. Разницы для меня в данном случае нет. Word - писать короче. Да и нет с ними проблемы.
Что возвращается:
если поставить Single, то 2,07446823360182E-40 (неправильно).
Если array [0..3] of byte, то 50,0126495361328 (правильно). B двоичном сейчас нет возможности показать.
  Вверх
_hunter
Дата 1.12.2004, 12:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 8564
Регистрация: 24.6.2003
Где: Europe::Ukraine:: Kiev

Репутация: 15
Всего: 98



а хоть в hex ( к нему и приводить проще и видно лучше чем так )


--------------------
Tempora mutantur, et nos mutamur in illis...
PM ICQ   Вверх
unreg
Дата 1.12.2004, 14:35 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Че-то, вообще, бред какой-то...

Вот структура:

TStruct = record
time: cardinal;
Vmax:word;
Smax:word;
FR: array [0..3] of byte;

Завел еще массив a:array [0..3] of byte;

Прочитал структуру и сделал Move(Struct.FR,a,4);
массив заполнился следующим: 60 0 72 66. (правильно)

Изменил описание FR на Single;

Прочитал структуру и сделал Move(Struct.FR,a,4);
массив заполнился следующим: 72 66 2 0. (не правильно)

Не смотря на мои эксперименты, остальные поля заполнялись верно.

А теперь самое интересное:

Изменил описание массива а: var a:array [0..5] of byte;
В структуре, поле FR описал точнно так же.
Прочитал структуру и сделал Move(Struct.FR,a,6);
массив заполнился следующим: 60 0 72 66 2 0 (дурдом на выезде) Да, еще забыл сказать, что эта струтктура в файле не единственная, он большой и там много всего.

Тем не менее:
Читаю по одному смещению. Количество байт строго определено. Что за кака?



  Вверх
<Spawn>
Дата 1.12.2004, 14:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Око кары:)
****


Профиль
Группа: Экс. модератор
Сообщений: 2776
Регистрация: 29.1.2003
Где: Екатеринбург

Репутация: 44
Всего: 64



Покажи как ты читаешь данные в структуру.

Я толька что проверил вот этот вариант:

Цитата
TStruct = record
time: cardinal;
Vmax:word;
Smax:word;
FR: array [0..3] of byte;

Завел еще массив a:array [0..3] of byte;

Прочитал структуру и сделал Move(Struct.FR,a,4);
массив заполнился следующим: 60 0 72 66. (правильно)

Изменил описание FR на Single;

Прочитал структуру и сделал Move(Struct.FR,a,4);
массив заполнился следующим: 72 66 2 0. (не правильно)


И у меня все работает нормально:

Код

TStruct = record
 time: cardinal;
 Vmax:word;
 Smax:word;
 FR: Single;
end;

var
 Form1: TForm1;
 struct: TStruct;
 a: array[0..3] of byte;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
 Move(Struct.FR, a, 4);
 ShowMessage(Format('%d %d %d %d', [a[3], a[2], a[1], a[0]]))
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 LongRec(Struct.FR).Bytes[0] := 66;
 LongRec(Struct.FR).Bytes[1] := 72;
 LongRec(Struct.FR).Bytes[2] := 0;
 LongRec(Struct.FR).Bytes[3] := 60;
end;


Отсюда напрашивается один вывод - ты как то не верно читаешь данные в TStruct.FR


--------------------
"Для некоторых людей программирование является такой же внутренней потребностью, подобно тому, как коровы дают молоко, или писатели стремятся писать" - Николай Безруков.
PM MAIL ICQ   Вверх
p0s0l
Дата 1.12.2004, 17:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Г-н Посол
****


Профиль
Группа: Экс. модератор
Сообщений: 3668
Регистрация: 13.7.2003
Где: 58°38' с.ш. 4 9°41' в.д.

Репутация: 58
Всего: 112



Судя по описанию - всё-таки возможно проблема в выравнивании...
Только непонятно, откуда она берётся - ведь структура уже выравнена. Если бы вместо Cardinal был Word, то да, была бы 100% такая проблема, если в опциях компилятора выставлено выравнивание 4 или 8 байт...

Единственное предположение, что ты где-то до описания этой структуры или в модулях, прописанных в Uses сделал описание кардинала таким:
Код
type cardinal = word;
Поэтому, если используешь массив байтов, то массив не выравнивается, т.к. байты не подлежат выравниванию.
Если делаешь Single - то он выравнивается по границе 4 байт, т.е. до FR вставятся два левых ненужных байта...

Но опять же если бы ты переопределил тип Cardinal, то первые три поля структуры заполнились бы не теми данными (ведь time должен быть 4 байта)...

Чтобы не гадать, скажи, что выдаёт у тебя SizeOf(TStruct) в случаях, если FR : array[0..3] of byte и FR : Single;

Также, всё-таки, на всякий случай (чем черт не шутит ?), напиши так:
Код
TStruct = packed record
time: cardinal;
Vmax:word;
Smax:word;
FR: single;

Или в опциях компилятора выстави Record Field Alignment в 1, или напиши вначале {$A1}

Также вместо массива FR : array [0..3] of byte попробуй написать FR : DWORD или FR : Integer, и cделать Move (как ты уже делал) - что будет в таком случае ?

Либо же проблема со чтением, как предположил <Spawn>...



--------------------
С уважением, г-н Посол.
PM   Вверх
unreg
Дата 6.12.2004, 05:30 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Извиняюсь, что долго не отвечал. Возможности не было.
PoSol, действительно, размер структуры меняется. Полностью моя структура выглядит так:
Код

type
  PMainStruct = ^TMainStruct;
  TMainStruct = record
  time:integer;
  VMax:word;
  SMax:word;
  OK:word;
  NPeriod:word;
  nMaxV:word;
  imaxV:word;
  nmaxS:word;
  imaxS:word;
  Na:word;
  Fr1:word;
  Reserv:word;
  fr:Single;//array [0..3] of byte;
  PREJ:word;
  PREJ2:word;
  DREJ:word;
end;


В случае с Single: SizeOf(TMainStruct) = 40,
в случае с array [0..3] of byte: SizeOf(TMainStruct) = 36.

Читаю структуру из файла:

var F:TFileStream;
//читаю по нулевому смещению, структура находится в начале файла;
F.Read(MainStruct,SizeOf(TMainStruct));

Видимо, дело действительно в выравнивании. Где в компиляторе находятся эти опции? И, если возможно, по-подробнее про выравнивание расскажите. Если я правильно понял, то под Single выделяется 8 байт как на Real, но значение имеют только 4?


  Вверх
<Spawn>
Дата 6.12.2004, 05:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Око кары:)
****


Профиль
Группа: Экс. модератор
Сообщений: 2776
Регистрация: 29.1.2003
Где: Екатеринбург

Репутация: 44
Всего: 64



Сделай packed record, как тебе уже сказал p0s0l, и будет у тебя структура занимать 36 байт.

Код

TMainStruct = packed record
...


Это сообщение отредактировал(а) <Spawn> - 6.12.2004, 05:46


--------------------
"Для некоторых людей программирование является такой же внутренней потребностью, подобно тому, как коровы дают молоко, или писатели стремятся писать" - Николай Безруков.
PM MAIL ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0616 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.