2016-12-05 63 views
2

我嘗試避免在QT程序中混合使用QStringchar*類型。我有一個會話函數,它返回QString中的數據指針,但是我得到了非常奇怪的結果。這段代碼有什麼問題?QString格式不起作用qDebug

編譯器和環境GCC(Debian的4.9.2-10)通過QMAKE 4.9.2 標誌: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! 

回答

2

給你複製QString函數,並返回指向已經銷燬的函數內的數據的指針。這是已知的未定義行爲,因爲您正在返回指向垃圾的指針。返回QString。

const char* CH(QString msg) { 
    const char* res = msg.toAscii().data(); 
    return res; 
} 
+0

感謝這一點清楚。除了宏還有其他的解決方案嗎? .. #define CH(m)(m.toAscii()。data())。 ? – huckfinn

+1

爲什麼不'qDebug()<< m'? – Starl1ght

+0

我喜歡通過預定義的錯誤代碼使用記錄功能的printf功能。類似這樣的:const QString ERR_UNKOWN_WORK_DIR =「%s:未知工作目錄%s」; – huckfinn

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-字符串。它在編譯時彙編a binary internal representation of a QString,並將其存儲在可執行文件的只讀存儲器部分。這是避免字符串編碼的運行時成本的唯一方法。

如果您已經使用UTF8編碼的字符串文本或UTF8編碼的C風格字符串,則通過QString執行往返操作並無任何好處。如果您需要使用C風格的字符串/字符串常量,直接與qDebug使用它們:如果您需要通過臨時C風格的字符串,請使用QByteArray

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

,但是這的確是一個很大的代碼非常少爲了展示它 - 這是非常詳細的,以至於有一個非常糟糕的代碼味道。所以不要這樣做:

#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()); 
}