Sebastien
Sebastien

Reputation: 23

Building QString out string

With the following piece of code:

QString msg;
msg =   "Datalogging Item"          + ',' +
        QString::number(item)       + ',' +
        "Slave Index"               + ',' +
        QString::number(slaveIndex) + ',' +
        "Slave Name"                + ',' +
        slaveName                   + ',' +
        "Experiment Index"          + ',' +
        QString::number(expIndex)   + ',' +
        "Experiment Name"           + ',' +
        expName                     + ',' +
        "Aquisition Frequency "     + ',' +
        "33 Hz"                     + "\n";
qDebug() << msg;

I was getting the following debug output

"riment Index0,Slave Index,0,Slave Name,Execute 1,Experiment Index,0,Experiment Name,Read All (Barebone),Aquisition Frequency ,33 Hz\n"

Which is not really what I was expected to get.

But with the code modified with the QString typecast:

QString msg;
msg =   QString("Datalogging Item")     + QString(',') +
        QString::number(item)           + QString(',') +
        QString("Slave Index")          + QString(',') +
        QString::number(slaveIndex)     + QString(',') +
        QString("Slave Name")           + QString(',') +
        slaveName                       + QString(',') +
        QString("Experiment Index")     + QString(',') +
        QString::number(expIndex)       + QString(',') +
        QString("Experiment Name")      + QString(',') +
        expName                         + QString(',') +
        QString("Aquisition Frequency ")+ QString(',') +
        QString("33 Hz")                + QString("\n");
qDebug() << msg;

I get what I expected to get:

"Datalogging Item,0,Slave Index,0,Slave Name,Execute 1,Experiment Index,0,Experiment Name,Read All (Barebone),Aquisition Frequency ,33 Hz\n"

Do you have any clue on what is going on? I just don't get what is going on and I'm a newbie to QT.

Thanks.

Upvotes: 0

Views: 1100

Answers (3)

The expression

"Datalogging Item" + ','

has the type and meaning of

static_cast<const char *>("Datalogging Item" + 44)

You're taking the address of the beginning of the Datalogging string constant and adding 44 to it - advancing it by 44 characters. This is undefined behavior as you're moving a pointer past the object it points to. By coincidence the pointer happens to point to another C string constant.

A short program that reproduces the issue:

#include <iostream>
int main() {
  std::cout << "Datalogging Item Foo Bar Baz" + '\n' << std::endl;
}

Output:

g Item Foo Bar Baz

One way of rewriting your expression to make it valid and less verbose would be to use the arg-substitution mechanism of QString:

auto msg = QStringLiteral(
  "Datalogging Item,%1,Slave Index,%2,Slave Name,%3,Experiment Index,%4,"
  "Experiment Name,%5,Acquisition Frequency,%6\n")
   .arg(item).arg(slaveIndex).arg(slaveName).arg(expIndex)
   .arg(expName).arg(QStringLiteral("33 Hz"));

If you're using Qt 4, replace QStringLiteral with QString::fromUtf8. The QStringLiteral is a mechanism introduced in Qt 5 that builds up a constant QString instance at compile time, yielding smaller code and better runtime performance than the use of a QString constructor.

Upvotes: 1

Xplatforms
Xplatforms

Reputation: 2232

It is better to use QStringLiteral macro for static string in code.

msg = QStringLiteral("Datalogging Item") + ',' +

More info here: http://doc.qt.io/qt-5/qstring.html#QStringLiteral

Upvotes: 0

selbie
selbie

Reputation: 104589

You can repro similar results even simpler:

 msg =   "Datalogging Item" + ',' +  QString::number(item);

And now it occurs to be exactly what the issue is. The first part of that expression is simply:

"Datalogging Item" + ','

In the above expression, a raw string literal is having the integer value of 44 (ascii val for comma) added to it's pointer address. Hence, you are now in "undefined" territory since the length of "Datalogging Item" is far less than 44 characters. Most likely what's happening is that the above expression is now a pointer expression into the middle of one of your other string literals defined nearby.

The solution is simply to declare the first element to be a QString so that all subsequent "additions" will use the overloaded + operator of QString:

msg =   QString("Datalogging Item") + ',' +
        QString::number(item)       + ',' +
        ...

Upvotes: 3

Related Questions