2

QT プログラムでは型QStringと型の混在を避けるようにしています。char*内のデータのポインターを返す会話関数がありますが、QString非常に奇妙な結果が得られます。このコードの何が問題なのですか?

コンパイラと環境 gcc (Debian 4.9.2-10) 4.9.2 qmake によるフラグ:QMAKE_CXXFLAGS += -std=c++11

コードスニペット:

#include <QCoreApplication>
#include <iostream>
#define  PCH(m) ( m.toAscii().data() )

// get the pointer short scripted
const char* CH(QString msg) {
   const char* res = msg.toAscii().data();
   return res;
}

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);

    const QString qformat = "%s does not work!";
    const QString qvalue  = "embedding";

    // Works not
    qDebug(CH(qformat), CH(qvalue));   

    // Works
    qDebug(qformat.toAscii().data(), qvalue.toAscii().data());

    // Works too but macro
    qDebug(PCH(qformat), PCH(qvalue));   

    return app.exec();
}

結果

%s does not work! does not work!

embedding does not work!

embedding does not work!
4

2 に答える 2

2

ここでは、関数にコピーQStringし、関数内の既に破棄されたデータへのポインターを返します。ガベージへのポインターを返すため、これは既知の未定義の動作です。QString を返します。

const char* CH(QString msg) {
    const char* res = msg.toAscii().data();
    return res;
}
于 2016-12-05T20:53:06.247 に答える
2

使用する必要があり、それ自体qDebug()に組み込まれたフォーマット メカニズムを使用する必要がありQStringます。また、デフォルトの文字列変換に依存する代わりに使用する必要がありますQStringLiteral-結局のところ、そのようなことを気にかけていると述べた後:

#include <QtCore>
int main()
{
    const auto qformat = QStringLiteral("%1 does work!");
    const auto qvalue = QStringLiteral("embedding");
    qDebug() << qformat.arg(qvalue);
    qDebug() << qformat.arg(0x7A01173C2, 0, 16);
}

QStringLiteral最新のコンパイラで使用される は、8 ビットの C 文字列を作成しません。コンパイル時にのバイナリ内部表現をQStringアセンブルし、実行可能ファイルの読み取り専用メモリ セクションに格納します。これは、文字列エンコーディングの実行時のコストを回避する唯一の方法です。

QStringUTF8 でエンコードされた文字列リテラルまたは UTF8 でエンコードされた C スタイルの文字列が既にある場合は、経由でラウンドトリップを実行しても何のメリットもありません。C スタイルの文字列/文字列リテラルを使用する必要がある場合は、次のように直接使用しますqDebug

#include <QtCore>
int main() {
    const char format[] = "%s does not work!";
    const char value[] = "embedding";
    qDebug(format, value);
}

一時的な C スタイルの文字列を渡す必要がある場合は、 を使用しますQByteArrayが、これは非常に多くのコードで、表示するものはほとんどありません。したがって、次のようにしないでください。

#include <QtCore>
QByteArray CH(const QString &msg) {
   return msg.toLocal8Bit();
}

int main()
{
    auto qformat = QStringLiteral("%s does work!");
    auto qvalue = QStringLiteral("embedding");
    qDebug(CH(qformat).constData(), CH(qvalue).constData());
}
于 2016-12-05T21:09:42.187 に答える