QString 格式化将不起作用 qDebug
QString formatting will not work qDebug
我尽量避免在 QT 程序中混合使用 QString
和 char*
类型。我有一个对话函数 returns 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!
此处您正在将 QString
复制到函数中,并将 return 指针指向函数内部已销毁的数据。这是已知的未定义行为,因为您正在 returning 指向垃圾的指针。 Return QString.
const char* CH(QString msg) {
const char* res = msg.toAscii().data();
return res;
}
您应该使用 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 字符串。它在编译时汇编 a binary internal representation of a QString
,并将其存储在可执行文件的只读内存部分。这是避免字符串编码的运行时成本的唯一方法。
如果您已经拥有 UTF8 编码的字符串文字或 UTF8 编码的 C 风格字符串,那么通过 QString
进行往返没有任何好处。如果你需要使用 C 风格的 strings/string 文字,直接使用 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());
}
我尽量避免在 QT 程序中混合使用 QString
和 char*
类型。我有一个对话函数 returns 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!
此处您正在将 QString
复制到函数中,并将 return 指针指向函数内部已销毁的数据。这是已知的未定义行为,因为您正在 returning 指向垃圾的指针。 Return QString.
const char* CH(QString msg) {
const char* res = msg.toAscii().data();
return res;
}
您应该使用 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 字符串。它在编译时汇编 a binary internal representation of a QString
,并将其存储在可执行文件的只读内存部分。这是避免字符串编码的运行时成本的唯一方法。
如果您已经拥有 UTF8 编码的字符串文字或 UTF8 编码的 C 风格字符串,那么通过 QString
进行往返没有任何好处。如果你需要使用 C 风格的 strings/string 文字,直接使用 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());
}