Russian Qt Forum

Qt => Общие вопросы => Тема начата: zayac_val от Март 20, 2009, 15:53



Название: Преобразовать символ из QChar в char
Отправлено: zayac_val от Март 20, 2009, 15:53
Вопрос примитивный, но ответ найти не получается. Подскажите как преобразовать символ из  QChar в char, или из QString в char ? ???


Название: Re: Преобразовать символ из QChar в char
Отправлено: igor_bogomolov от Март 20, 2009, 15:59
Цитировать
char QChar::toAscii () const
char QChar::toLatin1 () const

const char * qPrintable ( const QString & str )


Название: Re: Преобразовать символ из QChar в char
Отправлено: zayac_val от Март 20, 2009, 16:03
Спасибо. ;D


Название: Re: Преобразовать символ из QChar в char
Отправлено: nn1317 от Март 20, 2009, 19:08
Цитировать
char QChar::toAscii () const
char QChar::toLatin1 () const

const char * qPrintable ( const QString & str )
чувааак! респект и уважуха тебе!)))
а то я уже года 3-4 делаю так:
Код:
QString str;
char* ss = str.toAsii().data();


Название: Re: Преобразовать символ из QChar в char
Отправлено: pastor от Март 23, 2009, 10:14
Есть одно но:

Код
C++ (Qt)
const char *ss = qPrintable ( str );
char* ss = str.toAsii().data();

В обоих случаях ss будет невалиден и дальнейшая работа с ним приведет к крашу проги. Почему? Читать в ассистанте


Название: Re: Преобразовать символ из QChar в char
Отправлено: BRE от Март 23, 2009, 11:33
Есть одно но:

Код
C++ (Qt)
const char *ss = qPrintable ( str );
char* ss = str.toAsii().data();

В обоих случаях ss будет невалиден и бальнейшая работа с мин приведет к крашу проги. Почему? Читать в ассистанте
Дополню pastor'а. Причина будет одна, потому что qPrintable определено как:
Код
C++ (Qt)
#define qPrintable(string) (string).toLocal8Bit().constData();
 


Название: Re: Преобразовать символ из QChar в char
Отправлено: Barmaglodd от Март 23, 2009, 14:51
Есть одно но:

Код
C++ (Qt)
const char *ss = qPrintable ( str );
char* ss = str.toAsii().data();

В обоих случаях ss будет невалиден и дальнейшая работа с ним приведет к крашу проги. Почему? Читать в ассистанте


Зачем же так категорично? Если str не разрушать, и косяков с преобразованием из UTF нет, то вполне себе валиден, и работать можно ;)

тьфу, прогнал :(


Название: Re: Преобразовать символ из QChar в char
Отправлено: Racheengel от Март 23, 2009, 15:11
Есть одно но:

Код
C++ (Qt)
const char *ss = qPrintable ( str );
char* ss = str.toAsii().data();

В обоих случаях ss будет невалиден и дальнейшая работа с ним приведет к крашу проги. Почему? Читать в ассистанте


Не соглашусь, это стандартный механизм преобразования, рекомендуемый тролями, для доступа ReadOnly.
Конечно, если попытаться менять контент - может быть плохо, но не краш.


Название: Re: Преобразовать символ из QChar в char
Отправлено: BRE от Март 23, 2009, 15:16
Не соглашусь, это стандартный механизм преобразования, рекомендуемый тролями, для доступа ReadOnly.
Конечно, если попытаться менять контент - может быть плохо, но не краш.
Имеется ввиду следующее использование:
Код
C++ (Qt)
const char *func()
{
   QString str = "......";
   return qPrintable( str );
}
 
Хорошего от него не жди....  ;)


Название: Re: Преобразовать символ из QChar в char
Отправлено: pastor от Март 23, 2009, 15:35
Имеется ввиду следующее использование:

Нет, имеется ввиду какраз вот такое:

Код
C++ (Qt)
QString str("bla-bla");
 
const char *ptrStr = str.toLocal8Bit().constData();
 
//do something with ptrStr

Вот какраз на do something with ptrStr мы и получим краш, т.е. ptrStr будет не валиден после вызова toLocal8Bit().constData().

Эта тема уже поднималась ранее http://www.prog.org.ru/topic_3658_0.html


Название: Re: Преобразовать символ из QChar в char
Отправлено: pastor от Март 23, 2009, 15:38
Не соглашусь, это стандартный механизм преобразования, рекомендуемый тролями, для доступа ReadOnly.
Конечно, если попытаться менять контент - может быть плохо, но не краш.

А ты проверь ;) Можно также посмотреть исходники Qt на предмет toLocal8Bit


Название: Re: Преобразовать символ из QChar в char
Отправлено: BRE от Март 23, 2009, 15:46
А ты проверь ;) Можно также посмотреть исходники Qt на предмет toLocal8Bit
А я и проверять не буду, полностью соглашусь (сообразил).  ;D


Название: Re: Преобразовать символ из QChar в char
Отправлено: nn1317 от Март 23, 2009, 19:07
перечитал ту тему еще разок - дошло, почему у меня все работает))


Название: Re: Преобразовать символ из QChar в char
Отправлено: Racheengel от Март 23, 2009, 19:39
хм, ну вот скока себя помню - всегда работала подобная конструкция
(const char *ptrStr = str.toAscii().constData();)

естественно, что возвращать ptrStr не стоит :) но в локальном методе все ок.
QByteArray то живет до очистки стека.


Название: Re: Преобразовать символ из QChar в char
Отправлено: Rcus от Март 23, 2009, 20:02
В том то и дело, что не живет, Valgrind единозначно выражает мнение насчет подобных конструкций

Код
C++ (Qt)
int main(int argc, char *argv[])
{
   QString aaaa = QString("aaaaaBBBB");
   const char *astr = qPrintable(aaaa);
   qDebug("%s",astr);
   return 0;
}
valgrind --free-fill=0x55 ./test
Код:
==305== Invalid read of size 1
==305==    at 0x694EE0E: QString::fromUtf8(char const*, int) (in /usr/lib/libQtCore.so.4.5.0)
==305==    by 0x6951622: QString::vsprintf(char const*, __va_list_tag*) (in /usr/lib/libQtCore.so.4.5.0)
==305==    by 0x68FEDC7: qDebug(char const*, ...) (in /usr/lib/libQtCore.so.4.5.0)
==305==    by 0x40E2E1: main (main.cpp:20)
==305==  Address 0xbd35a68 is 24 bytes inside a block of size 41 free'd
==305==    at 0x4C265AF: free (vg_replace_malloc.c:323)
==305==    by 0x40E2D2: main (main.cpp:19)
UUUUUUUUUUUUUUUUU


Название: Re: Преобразовать символ из QChar в char
Отправлено: BRE от Март 23, 2009, 20:15
хм, ну вот скока себя помню - всегда работала подобная конструкция
(const char *ptrStr = str.toAscii().constData();)
Это скорее удача, хотя нужно смотреть код, что там компилятор "нагенерил".

естественно, что возвращать ptrStr не стоит :) но в локальном методе все ок.
QByteArray то живет до очистки стека.
Эту конструкцию (const char *ptrStr = str.toAscii().constData();) можно записать так:
Код
C++ (Qt)
const char *ptrStr;
{
    QByteArray tmp = str.toAscii();
    ptrStr = tmp.constData();
}
 
Вот если бы деструктор QByteArray занулял бы свою область, то вопросов бы не возникало.


Название: Re: Преобразовать символ из QChar в char
Отправлено: Racheengel от Март 24, 2009, 12:39
Наскольно мне известно, в С++ областью "жизни" локального объекта является блок скобок {...}. Таким образом, два вышеприведенных варианта аналогичны, за исключением того, что в первом создается неименованный экземпляр QByteArray для локального доступа, а во втором он получает имя tmp. Прибиты же оба должны быть при выходе из блока, т.е. после первой всреченной }.
Однако согласен, что все может зависеть от реализации компилятора. Могу только сказать, что по крайней мере я не встречал компиляторов, которые бы некорректно отрабатывали данную ситуацию (но это, как про суслика - его можно не видеть, хотя он есть - ДМБ).


Название: Re: Преобразовать символ из QChar в char
Отправлено: Rcus от Март 24, 2009, 12:51
/** sigh, \image html facepalm.jpg, \ref Valgrind-free-fill-proof */


Название: Re: Преобразовать символ из QChar в char
Отправлено: BRE от Март 24, 2009, 12:52
Наскольно мне известно, в С++ областью "жизни" локального объекта является блок скобок {...}. Таким образом, два вышеприведенных варианта аналогичны, за исключением того, что в первом создается неименованный экземпляр QByteArray для локального доступа, а во втором он получает имя tmp. Прибиты же оба должны быть при выходе из блока, т.е. после первой всреченной }.
Ну да, а использовать указатель на tmp, ты будешь после }.

Вариант 1
Код
C++ (Qt)
const char *ptrStr;
{
    QByteArray tmp = str.toAscii();
    ptrStr = tmp.constData();
}
 
// Использование
char ch = ptrStr[ 20 ];
 

Вариант 2
Код
C++ (Qt)
const char *ptrStr = str.toAscii().constData()
 
// Использование
char ch = ptrStr[ 20 ];
 

В обоих случаях объект на который указывает ptrStr уже разрушен.


Название: Re: Преобразовать символ из QChar в char
Отправлено: Racheengel от Март 24, 2009, 13:02
В 1 случае - однозначно, во 2 - depends on compiler.
Стандарт С++ не утверждает, что локальный объект должен уничтожаться в этом случае.


Название: Re: Преобразовать символ из QChar в char
Отправлено: BRE от Март 24, 2009, 13:08
во 2 - depends on compiler.
Стандарт С++ не утверждает, что локальный объект должен уничтожаться в этом случае.
По стандарту утверждать не буду, не владею информацией....
Но во избежании, лучше не использовать.
А то может получиться сегодня работает, вышла новая версия компилятора и программа умирает. Можно долго голову ломать, а потом долго все вычищать.
Все IMHO.  ;)


Название: Re: Преобразовать символ из QChar в char
Отправлено: spirit от Март 24, 2009, 13:11
во 2 - depends on compiler.
Стандарт С++ не утверждает, что локальный объект должен уничтожаться в этом случае.
По стандарту утверждать не буду, не владею информацией....
Но во избежании, лучше не использовать.
А то может получиться сегодня работает, вышла новая версия компилятора и программа умирает. Можно долго голову ломать, а потом долго все вычищать.
Все IMHO.  ;)
+1, зачем использовать заведомо нестабильный код.


Название: Re: Преобразовать символ из QChar в char
Отправлено: pastor от Март 24, 2009, 13:17
во 2 - depends on compiler.

Невстречал такого. Валится прога и на GCC и на MSVC и на ICC по одной и тойже причине - указатель невалиден в виду того что разрущается объект QByteArray. И это не зависит от компилятора или платформы. Для интереса провери ряд тестов, с разными компиляторами, платформами.

ЗЫ: Повторюсь еще раз, загляните в исходники самой Qt на предмет использования таких вот конструкций.


Название: Re: Преобразовать символ из QChar в char
Отправлено: BRE от Март 24, 2009, 13:20
Невстречал такого. Валится прога и на GCC и на MSVC и на ICC по одной и тойже причине - указатель невалиден в виду того что разрущается объект QByteArray
Скорее всего, срабатывает то, что деструктор вызван, но данные лежат в стеке ничем не затертые. Вот если бы деструктор QByteArray занулял свои данные, такие номера скорее всего не проходили бы.


Название: Re: Преобразовать символ из QChar в char
Отправлено: pastor от Март 24, 2009, 13:22
Стандарт С++ не утверждает, что локальный объект должен уничтожаться в этом случае.

Непонял. А почему он недолжен разрушатся?

У нас отработал комплекс функций str.toAscii().constData(). Локальный объекты умерли, память освободилась, но указатель на эти данные мы сохранили. На что будет указывать этот указатель?

А вот в таких ситуациях будет все ок:

Код
C++ (Qt)
qWarning("%s", str.toAscii().constData());

или

...
Код
C++ (Qt)
some_function(str.toAscii().constData());
....
 
void some_function(const char *str)
{
   //do something with str
}


Название: Re: Преобразовать символ из QChar в char
Отправлено: Racheengel от Март 24, 2009, 13:26
А вот тут поподробнее плиз...
Почему тогда будет все ок, если компиль прибьет локальный объект?



Название: Re: Преобразовать символ из QChar в char
Отправлено: BRE от Март 24, 2009, 13:29
А вот тут поподробнее плиз...
Почему тогда будет все ок, если компиль прибьет локальный объект?
Локальный объект создается, указатель передается в функцию, функция отрабатывает, при выходе из функции локальный объект уничтожается.


Название: Re: Преобразовать символ из QChar в char
Отправлено: Racheengel от Март 24, 2009, 13:30
У нас отработал комплекс функций str.toAscii().constData(). Локальный объекты умерли, память освободилась

Вот, собственно, почему они должны умереть? Стандарт не говорит об этом.


Название: Re: Преобразовать символ из QChar в char
Отправлено: pastor от Март 24, 2009, 13:37
А вот тут поподробнее плиз...
Почему тогда будет все ок, если компиль прибьет локальный объект?

Указатель, переданный в some_function будет оставаться валидным до её завершения, так как временный экземпляр QByteArray остаётся жить в стеке и будет уничтожен сразу же при выходе из этой функции


Название: Re: Преобразовать символ из QChar в char
Отправлено: Racheengel от Март 24, 2009, 14:16
ну ок, в случае с функцией это да.
А вот такой код -

Код:
{
...
const char *ptrStr = str.toAscii().constData();
...
doSomething(ptrStr);
...
}

очень часто употребляем, и реально я не вижу причин, по которому бы временный экземпляр QByteArray был бы прибит до }. По крайней мере, согласно стандарту. (хотя создатели компилятора могут думать по другому)


Название: Re: Преобразовать символ из QChar в char
Отправлено: pastor от Март 24, 2009, 15:03
ну ок, в случае с функцией это да.
А вот такой код -

А вот в таком коде получим невалидный указатель.

1) Вызвали toAscii (создался временный объект QByteArray)
2) вызвали constData() - получили указатель на данные временного объекта QByteArray
3) Сохранили указатель в ptrStr. Вроде все ок, но..
4) При переходе к следующей интсрукции - вызов doSomething - временный объект QByteArray разрушается за ненадобностью. Он свое дело сделал. Но у нас остался указатель на его данные.

Думаю что из этого следует понятно..


Название: Re: Преобразовать символ из QChar в char
Отправлено: Racheengel от Март 24, 2009, 15:36
Почему краш будет, если "временный объект QByteArray разрушается за ненадобностью" это понятно :)
Я к тому, что это самое разрушение зависит чисто от компилятора, т.к. оно не определено стандартом.
Не факт, что компиль его прибьет.


Название: Re: Преобразовать символ из QChar в char
Отправлено: pastor от Март 24, 2009, 15:50
Арс, я вот непойму одного, почему ты думаешь что это зависит от компилятора?

К примеру код:

Код
C++ (Qt)
const char *data = 0;
 
{
   QByteArray arr;
   data = arr.constData();
}
 
//do something with data

будет зависить от компилятора? Такого если чесно не встричал и неслыхал. Мы вышли из области видимости, arr разрушился. Что тут может зависить от компилятора?


Название: Re: Преобразовать символ из QChar в char
Отправлено: Racheengel от Март 24, 2009, 16:12
Такой код - не будет :)
А
Код:
data = str.toAscii().constData()
в общем случае будет, т.к. область видимости для неявного QByteArray теоретически может быть всем методом (или блоком скобок). Тут уже как разработчики компилятора задумали :)

Ну т.е. есть 2 варианта трансляции кода вроде сonst char *data = str.toAscii().constData(); doSomething(data);

1.
Код:
const char *data;
QByteArray tmp = str.toAscii();
data = tmp.constData();
doSomething(data);

и 2.
Код:
const char *data;
{
QByteArray tmp = str.toAscii();
data = tmp.constData();
}
doSomething(data);   // тут жопо

Вот я о чем :) какой из вариантов выберет компилятор (1 или 2) - в общем случае нигде не определено.