Несколько головоломок о std :: basic_string на солярисе (x86) - PullRequest
4 голосов
/ 14 ноября 2011

Несколько загадок о std :: basic_string on solaris (x86)

#include <iostream>
#include <string>
int main()
{
    const wchar_t* s = L"abcdef";
    std::wstring ws(s, s+6);
    for(int i = 0; i < ws.size(); ++i)
    {
        std::cout << ws[i] << std::endl;
    }
    return 0;
}

Результат выполнения:

97
99
101
0
0
0

Почему не

97
98
99
100
101
102

и код

#include <iostream>
#include <string>
int main()
{
    const wchar_t* s = L"abcdef";
    std::wstring ws;
    ws.resize(6);       
    for(int i = 0; i < ws.size(); ++i)
    {
        std::cout << (ws[i] = s[i]) << std::endl;
    }
    return 0;
}

может получить ожидаемый результат. Я использую gcc 3.4.6, команда сборки - g++ -fshort-wchar stringtest.cpp. Кто-нибудь может дать expain?

Ответы [ 3 ]

5 голосов
/ 14 ноября 2011

Документация -fshort-wchar читает,

-fshort-wchar

Переопределите базовый тип для wchar_t, чтобы он был short unsigned int вместо значения по умолчанию для цели. Эта опция полезна для создания программ для запуска под WINE.

Предупреждение: ключ -fshort-wchar заставляет GCC генерировать код, который не совместим двоично с кодом, сгенерированным без этого переключателя. Используйте его для соответствия бинарному интерфейсу приложения не по умолчанию.

Таким образом, кажется, что этот флаг вызывает наблюдаемое несоответствие, и поскольку спецификация языка не говорит о таком флаге, поведение можно классифицировать как определяемое реализацией, так и неопределенное.


В качестве идентификатора вы должны использовать wcout вместо cout при работе с широкими символами, так как wcout предназначен для обработки широких символов:

  • cout является объектом типа basic_ostream<char>.
  • wcout - это объект типа basic_ostream<wchar_t>.

Думаю, в этом случае проблема не в том, что вы используете для печати значения, так как вы в любом случае говорите компилятору трактовать wchar_t как short unsigned int.

2 голосов
/ 14 ноября 2011

Стандартная библиотека, скорее всего, не была скомпилирована с --short-wchar. Этот флаг изменяет ABI, хотя он остается незамеченным, поскольку искажение имени не изменяется.

0 голосов
/ 14 ноября 2011

Похоже, проблема в ws[i], дающем неправильный результат; строка, кажется, содержит ожидаемые данные, когда я смотрю на сырую память. Довольно странно, почему это происходит; насколько я вижу, operator[] просто разыменовывает указатель на wchar_t, который работает правильно в других местах (например, печать s[i] в вашем втором примере). Эта проблема также возникает в более поздних версиях GCC (я пробовал 4.6.1) и в Linux.

Вы можете обойти это, используя *(ws.begin() + i).

...