Проблема здесь в том, что вы лжете компилятору, а компилятор доверяет вам. Используя Embedded Visual C ++, я предполагаю, что вы нацелены на Windows CE. Windows CE предоставляет только поверхность API Unicode, поэтому ваш проект, скорее всего, будет использовать Unicode (кодировка UTF-16 LE).
В этом случае CString
расширяется до CStringW
, в котором кодовые единицы хранятся как wchar_t
. Делая (const char*) (LPCTSTR) str
, вы затем кастуете с wchar_t const*
на char const*
. Учитывая ввод, первый байт имеет значение 52 (кодировка ASCII для символа 4
). Второй байт имеет значение 0. Это интерпретируется как терминатор строки в стиле C. Другими словами, вы передаете строку "4"
на ваш вызов atof
. Естественно, в результате вы получите значение 4.0
.
Чтобы исправить код, используйте что-то вроде следующего:
CStringW str = L"4.5";
double var = _wtof( str.GetString() );
_wtof является специфическим для Microsoft расширением CRT.
Обратите внимание на две особенности:
- В коде используется вариант
CString
с явным кодированием символов (CStringW
). Всегда будьте откровенны в отношении ваших строковых типов. Это помогает читать ваш код и отлавливать ошибки до того, как они произойдут (хотя все эти приведения в стиле C в исходном коде полностью опровергают это).
- Код вызывает элемент CString :: GetString для получения указателя на неизменяемый буфер. Это также облегчает чтение кода, поскольку не использует то, что выглядит как приведение в стиле C (но вместо этого - оператор).
Также рассмотрите возможность определения макроса _CSTRING_DISABLE_NARROW_WIDE_CONVERSION , чтобы предотвратить случайное преобразование набора символов (например, CString str = "4.5";
). Это также поможет вам рано обнаруживать ошибки (если только вы не победите их с помощью приведения в стиле C).