Russian Qt Forum

Qt => Вопросы новичков => Тема начата: OKTA от Август 24, 2012, 10:00



Название: [РЕШЕНО] Приведение типа.
Отправлено: OKTA от Август 24, 2012, 10:00
Товарищи! Вопрос! Есть ли возможность без приведения типов засунуть например в QByteArray данные, если я знаю указатель на них и их размер? Указатель соответственно левого типа!


Название: Re: Приведение типа.
Отправлено: Bepec от Август 24, 2012, 10:12
Неа, вроде. Нужно указатель привести к нужному типу. У тебя компилятор с ума сойдёт по идее.

PS хотя вон недавно библиотеку собирать пытался одну - там какой то компилятор использовался С++, который позволял всякие массивы переменной длины, так что мб и есть такие компиляторы :D


Название: Re: Приведение типа.
Отправлено: LisandreL от Август 24, 2012, 10:12
Простой вариант с приведением:
Код
C++ (Qt)
byteArray.append( reinterpret_cast< const char * >( &data ), size );

А без приведения можно через QDataStream сериализацию сделать определив:
Код
C++ (Qt)
QDataStream& operator << ( QDataStream& out, const YourData& data );
QDataStream& operator >> ( QDataStream& in, YourData& data );
Но кода будет значительно больше, зато можно адекватно сохранять динамические данные.


Название: Re: Приведение типа.
Отправлено: andrew.k от Август 24, 2012, 10:24
Код
C++ (Qt)
QByteArray QByteArray::fromRawData ( const char * data, int size )
QByteArray & QByteArray::setRawData ( const char * data, uint size )
при этом буфер должен оставаться валидным, пока используется массив, буфер нужно будет удалить самостоятельно, QByteArray его не удалит.


Название: Re: Приведение типа.
Отправлено: OKTA от Август 24, 2012, 10:29
Код:
byteArray.append( reinterpret_cast< const char * >( &data ), size );
Да, вот этот вариант работает! Попутно прочел, что reinterpret_cast - самый опасный способ и результат не всегда гарантирован!

с RawData не пойдет, т.к. указатель все равно надо перед этим привести к char!


Название: Re: Приведение типа.
Отправлено: Bepec от Август 24, 2012, 10:32
reinterpret_cast - Программист сам дурак, если ошибся :D :D
dynamic_cast - я всё за тобой проверю :D


Название: Re: Приведение типа.
Отправлено: andrew.k от Август 24, 2012, 10:36
Код:
byteArray.append( reinterpret_cast< const char * >( &data ), size );
Да, вот этот вариант работает! Попутно прочел, что reinterpret_cast - самый опасный способ и результат не всегда гарантирован!
А это че типа не приведение типа?

с RawData не пойдет, т.к. указатель все равно надо перед этим привести к char!
А у тебя какая-то детская фобия, что ты типы боишься приводить?

А вообще, похоже ты что-то делаешь не так.
append копирует данные кстати.


Название: Re: Приведение типа.
Отправлено: LisandreL от Август 24, 2012, 10:56
dynamic_cast - я всё за тобой проверю :D
В данном случае он не применим, так как типы скорее всего не приводимы.


с RawData не пойдет, т.к. указатель все равно надо перед этим привести к char!
ORLY?
То что кастуется к char не означает, что оно по нулю закончится.


Название: Re: Приведение типа.
Отправлено: OKTA от Август 24, 2012, 10:58
Как я понял, без приведения никак, поэтому и говорю, что вариант работает)
Да, сам понял, что append копирует уже, пробую с setRawData! Спасибо!
А почему кажется, что что-то не так?))) Не сразу просто вдуплил в твой совет с setRawData - не свел одно к другому в торопях))

Ужас какой вычитал!

dynamic_cast<derv_class *>(base_class_ptr_expr)
Используется RTTI (Runtime Type Information), чтобы привести один указатель на объект класса к другому указателю на объект класса. Классы должны быть полиморфными, то есть в базовом классе должна быть хотя бы одна виртуальная функция. Если эти условие не соблюдено, ошибка возникнет на этапе компиляции. Если приведение невозможно, то об этом станет ясно только на этапе выполнения программы и будет возвращен NULL.


Название: Re: Приведение типа.
Отправлено: OKTA от Август 24, 2012, 11:00
Dynamic_cast не подойдет, т.к. const char * не указатель на класс!! 


Название: Re: Приведение типа.
Отправлено: OKTA от Август 24, 2012, 11:14
Или я что-то недопонимаю?)


Название: Re: Приведение типа.
Отправлено: Kurles от Август 24, 2012, 12:14
Или я что-то недопонимаю?)
Всё правильно понимаешь )


Название: Re: [РЕШЕНО] Приведение типа.
Отправлено: Igors от Август 24, 2012, 13:07
Код:
byteArray.append( reinterpret_cast< const char * >( &data ), size );
Да, вот этот вариант работает! Попутно прочел, что reinterpret_cast - самый опасный способ и результат не всегда гарантирован!
Эта запись равноценна
Код
C++ (Qt)
byteArray.append( (char *) &data, size );
 
В обоих случаях это плохо, проблемы с доставанием записанного назад практически обеспечены. Достоинство reinterpret_cast в том что эта длинная сопля бросается в глаза и как бы сигналит "здесь плохо"  :)


Название: Re: [РЕШЕНО] Приведение типа.
Отправлено: Bepec от Август 24, 2012, 13:10
Достоинство реинтерпрет каста в том, что из 1 байта при помощи такой то матери, он может сделать трёхмерную матрицу и не падать в 50% случае.


Название: Re: Приведение типа.
Отправлено: andrew.k от Август 24, 2012, 13:21
А почему кажется, что что-то не так?))) Не сразу просто вдуплил в твой совет с setRawData - не свел одно к другому в торопях))
Потому что у тебя массив данных хранится не в массиве чаров, а непонятно в чем и тебе приходится что-то приводить. Всякого рода IO девайсы работают обычно с массивом чаров (я о сторонних библиотеках). Откуда у тебя что-то другое не ясно.
а с setRawData тебе надо все время помнить, что массив данных должен жить, до тех пор, пока ты работаешь с экземпляром QByteArray, даже если ты его передал в сигнале или параметром.


Название: Re: [РЕШЕНО] Приведение типа.
Отправлено: Пантер от Август 24, 2012, 13:24
Лучше сделай нормальную сериализацию и не парь себе мозг.


Название: Re: [РЕШЕНО] Приведение типа.
Отправлено: andrew.k от Август 24, 2012, 13:25
Достоинство реинтерпрет каста в том, что из 1 байта при помощи такой то матери, он может сделать трёхмерную матрицу и не падать в 50% случае.
он ничего не делает, он просто закрывает глаза компилятору на твой беспредел.
поэтому твои программы падают в 50% случаев.
как уже было сказано выше, это банальное приведение типов, только в красивом синтаксисе, и как справедливо заметил Игорс, оно привлекает внимание, что может как-нибудь пригодиться.


Название: Re: [РЕШЕНО] Приведение типа.
Отправлено: Bepec от Август 24, 2012, 13:27
Не ври :)

Мои программы не падают :)

А reinterpret_cast - приведение типа в формате С++
А (char)  - приведение в стиле С

В том и разница :D


Название: Re: [РЕШЕНО] Приведение типа.
Отправлено: Пантер от Август 24, 2012, 13:31
Мои программы не падают :)
Запускать-то пробовал? ;D


Название: Re: [РЕШЕНО] Приведение типа.
Отправлено: Igors от Август 24, 2012, 14:18
Достоинство реинтерпрет каста в том, что из 1 байта при помощи такой то матери, он может сделать трёхмерную матрицу и не падать в 50% случае.
Матрица - это таблица, насколько мне известно, она трехмерной не бывает :) Если Вы имели ввиду что-то "особо тонкое" - поясните на живом примере, иначе впечатление что Вы просто несете околесицу (толкаете фуфло и.т.п.)  :)


Название: Re: [РЕШЕНО] Приведение типа.
Отправлено: Bepec от Август 24, 2012, 14:23
Исправлюсь :D Матрица с 3 измерениями ;) 


Название: Re: [РЕШЕНО] Приведение типа.
Отправлено: andrew.k от Август 24, 2012, 14:30
Достоинство реинтерпрет каста в том, что из 1 байта при помощи такой то матери, он может сделать трёхмерную матрицу и не падать в 50% случае.
Матрица - это таблица, насколько мне известно, она трехмерной не бывает :) Если Вы имели ввиду что-то "особо тонкое" - поясните на живом примере, иначе впечатление что Вы просто несете околесицу (толкаете фуфло и.т.п.)  :)
Игорс, ты давно на форуме?  ;D
Главная фишка Вереса писать чушь с серьезным видом)


Название: Re: [РЕШЕНО] Приведение типа.
Отправлено: Пантер от Август 24, 2012, 14:34
Понеслась.

Матрица - вообще кинотрилогия про Нео.


Название: Re: [РЕШЕНО] Приведение типа.
Отправлено: Bepec от Август 24, 2012, 14:48
Ну как вам описать matrix с 3 dimension ? :D


Название: Re: [РЕШЕНО] Приведение типа.
Отправлено: Serr500 от Август 24, 2012, 15:12
{aijk: i=1,...,N1, j=1,...,N2, k=1,...,N3}  ;)


Название: Re: [РЕШЕНО] Приведение типа.
Отправлено: Bepec от Август 24, 2012, 15:30
Ну вот, а они смеются... Бяки  :-[


Название: Re: [РЕШЕНО] Приведение типа.
Отправлено: andrew.k от Август 24, 2012, 15:38
Ну вот, а они смеются... Бяки  :-[
"Если над вами смеются, то вы приносите людям радость"


Название: Re: [РЕШЕНО] Приведение типа.
Отправлено: Bepec от Август 24, 2012, 15:39
Я горд собой, что приношу вам, бякам, радость.  ;D


Название: Re: [РЕШЕНО] Приведение типа.
Отправлено: andrew.k от Август 24, 2012, 15:45
Я горд собой, что приношу вам, бякам, радость.  ;D
зря горд. ты доказал, что это не всегда работает)


Название: Re: [РЕШЕНО] Приведение типа.
Отправлено: OKTA от Август 24, 2012, 16:00
У меня просто сторонняя библиотека, у которой прописаны свои типы данных, дабы охватить наибольшее количество платформ, поэтому и не хранится там ничего в стандартных типах, типа тех же чаров! А насчет reinterpret_cast - если знаешь, что типы приводятся друг к другу, то как может работать 50 на 50? Если приводится, то приводится, если нет, то нет)))


Название: Re: [РЕШЕНО] Приведение типа.
Отправлено: andrew.k от Август 24, 2012, 16:11
У меня просто сторонняя библиотека, у которой прописаны свои типы данных, дабы охватить наибольшее количество платформ, поэтому и не хранится там ничего в стандартных типах, типа тех же чаров! А насчет reinterpret_cast - если знаешь, что типы приводятся друг к другу, то как может работать 50 на 50? Если приводится, то приводится, если нет, то нет)))
Обычно там что-то вроде #typedef char * LibCharArray, такие типы компилятор должен автоматом приводить, к стандартным.
А вообще похоже Пантер прав про сериализацию.


Название: Re: [РЕШЕНО] Приведение типа.
Отправлено: OKTA от Август 24, 2012, 18:25
Нет, не приводит автоматически!  А чем сериализация выигрывает?


Название: Re: [РЕШЕНО] Приведение типа.
Отправлено: andrew.k от Август 24, 2012, 18:56
Нет, не приводит автоматически!  А чем сериализация выигрывает?
Удобнее и логичнее, наверное.


Название: Re: [РЕШЕНО] Приведение типа.
Отправлено: andrew.k от Август 24, 2012, 19:03
Нет, не приводит автоматически!
А gcc приводит совершенно спокойно. Думаю и остальные должны.
upd. mingw тоже все прекрасно кушает.

Код
C++ (Qt)
typedef char * MyString;
 
{
 MyString s = "test string";
 printf("s = %s"\n", s);
 qDebug() << QString(s);
}
Все прекрасно работает без приведений :)


Название: Re: [РЕШЕНО] Приведение типа.
Отправлено: Alex Custov от Август 24, 2012, 19:11
Нет, не приводит автоматически!  А чем сериализация выигрывает?

код?


Название: Re: [РЕШЕНО] Приведение типа.
Отправлено: Igors от Август 24, 2012, 20:20
А gcc приводит совершенно спокойно. Думаю и остальные должны.
upd. mingw тоже все прекрасно кушает.

Код
C++ (Qt)
typedef char * MyString;
 
{
 MyString s = "test string";
 printf("s = %s"\n", s);
 qDebug() << QString(s);
}
Все прекрасно работает без приведений :)
??? А какие тут приведения? У qDebug есть оператор << принимающий QString (экземпляр которого Вы создали)

Нет, не приводит автоматически!  А чем сериализация выигрывает?
Тем что это солидно и надежно. Рано или поздно сериализовать придется. Без этого воспользоваться записанным (raw data) проблематично, считанный объект легко может оказаться невалидным. Все начинают с такого чтенмя/записи как у Вас, и все равно приходят к сериализации (вопрос времени)


Название: Re: [РЕШЕНО] Приведение типа.
Отправлено: andrew.k от Август 24, 2012, 22:55
А gcc приводит совершенно спокойно. Думаю и остальные должны.
upd. mingw тоже все прекрасно кушает.

Код
C++ (Qt)
typedef char * MyString;
 
{
 MyString s = "test string";
 printf("s = %s"\n", s);
 qDebug() << QString(s);
}
Все прекрасно работает без приведений :)
??? А какие тут приведения? У qDebug есть оператор << принимающий QString (экземпляр которого Вы создали)
приведений масса. Конечно не в qDebug, а в QString. Откуда он знает про новый тип MyString? Не знает, а компилятор выполняет автоматическое приведение типов, т.к. они совместимы с известным кустрингу char *.
C printf может и не удачный пример, там параметры хитро передаются.
В любом случае везде где на входе будет char *, можно будет подавать MyString, в отличие например от С, где типизация более строгая и такой фокус не прокатит, если мне не изменяет память.
и надо было бы писать QString((char *)s), если бы в С были были кустринги)


Название: Re: [РЕШЕНО] Приведение типа.
Отправлено: kambala от Август 24, 2012, 23:29
typedef не создает новых типов, а лишь создает алиасы (новые имена, псевдонимы), поэтому при компиляции там будет именно char *


Название: Re: [РЕШЕНО] Приведение типа.
Отправлено: andrew.k от Август 24, 2012, 23:40
typedef не создает новых типов, а лишь создает алиасы (новые имена, псевдонимы), поэтому при компиляции там будет именно char *
Действительно. typeid возвращает одно и тоже для этих типов.
Видимо мои знания устарели или уже забыл, но в Си без плюсов это был разные типы на сколько я помню.
По крайней мере в том компиляторе, что был у меня)

В любом случае в библиотеках собственные типы часто делаются через typedef, что подтвердил ТС.
Поэтому я и стал спрашивать, почему у него что-то не приводится.


Название: Re: [РЕШЕНО] Приведение типа.
Отправлено: kambala от Август 25, 2012, 02:06
нет, в С точно так же, хотя правильнее было бы сказать «в С++ точно так же, как и в С»


Название: Re: [РЕШЕНО] Приведение типа.
Отправлено: OKTA от Август 25, 2012, 08:20
Так, сериализация - перевод структуры в последовательность бит - верно? Если у меня есть указатель на данные и их длина, то данные уже сериализированы? Или я путаю?


Название: Re: [РЕШЕНО] Приведение типа.
Отправлено: Igors от Август 25, 2012, 12:35
Так, сериализация - перевод структуры в последовательность бит - верно?
Ну можно и так сказать, только байт а не бит.

Если у меня есть указатель на данные и их длина, то данные уже сериализированы? Или я путаю?
Путаете. Сериализации создает "хранимые" данные, т.е. то из чего десериализацией можно снова получить объект/структуру. Эти данные не равны дампу структуры в памяти. Простой пример
Код
C++ (Qt)
struct MyStruct {
int mID;
char * mName;
};
 
Добавив MyStruct в QByteArray (как у Вас сейчас) Вы затем не сможете его восстановить.

Действительно. typeid возвращает одно и тоже для этих типов.
Видимо мои знания устарели или уже забыл, но в Си без плюсов это был разные типы на сколько я помню.
По крайней мере в том компиляторе, что был у меня)
Наверное имелось ввиду объявление структуры на С
Код
C++ (Qt)
typedef struct {
int mID;
...
} MyStruct, * MyStructPtr;
 
Все равно нового типа typedef не создает, просто дает безымянной структуре имя