__int64 CString 返回错误的值 - C++ MFC
__int64 to CString returns wrong values - C++ MFC
我想将__int64变量转换为CString。代码正是这个
__int64 i64TotalGB;
CString totalSpace;
i64TotalGB = 150;
printf("disk space: %I64d GBn", i64TotalGB);
totalSpace.Format(_T("%I64d", i64TotalGB));
printf("totalSpace contains: %s", totalSpace);
第一幅 Printf 打印
"disk space: 150GB"
这是正确的,但是第二个printf打印随机高数字,例如"totalSpace contains: 298070026817519929"
我还尝试使用 INT64 变量而不是 __int64 变量,但结果是一样的。这是什么原因造成的?
在这里:
totalSpace.Format(_T("%I64d", i64TotalGB));
您将i64TotalGB
作为参数传递给_T()
宏,而不是将其作为第二个参数传递给Format()
。
试试这个:
totalSpace.Format(_T("%I64d"), i64TotalGB);
话虽如此,由于MS在字符编码方面的混乱(ha(,在这里使用_T
并不是正确的事情,因为CString
是由TCHAR
而不是_TCHAR
组成的。因此,考虑到这一点,不妨使用TEXT()
而不是T()
,因为它取决于UNICODE
而不是_UNICODE
:
totalSpace.Format(TEXT("%I64d"), i64TotalGB);
此外,此行是错误的,因为它尝试将 ATLCString
作为char*
传递(也称为C 样式字符串(:
printf("totalSpace contains: %s", totalSpace);
编译器对此发出以下警告:
warning C4477: 'printf' : format string '%s' requires an argument of type 'char *', but variadic argument 1 has type 'ATL::CString'
虽然CString
的结构实际上与像您一样传递它兼容,但这仍然是形式上未定义的行为。使用CString::GetString()
来防范它:
printf("totalSpace contains: %ls", totalSpace.GetString());
请注意,在我的配置下%ls
totalSpace.GetString()
返回了一个const wchar_t*
。但是,由于">printf
当前不支持输出到 UNICODE 流中">,因此此行的正确版本(将支持当前代码页之外的字符(是按以下方式调用wprintf()
:
wprintf("totalSpace contains: %s", totalSpace.GetString());
说了这么多,这里有一个一般性的建议,不管问题背后的直接问题是什么。如今更好的做法略有不同,我引用了@IInspectable的可敬回答,说"泛型文本映射在 20 年前是相关的"。
还有什么选择?如果没有足够充分的理由,请尝试显式坚持使用CStringW
(支持 CRT 的 Unicode 字符类型字符串(。首选L
字符文本,而不是古老的数据/文本映射,后者取决于程序中是否定义了常量_UNICODE
或_MBCS
。相反,更好的做法是使用所有 API 和语言库调用的宽字符版本,例如wprintf()
而不是printf()
。
该错误是代码中许多问题的结果,特别是以下两个问题:
-
totalSpace.Format(_T("%I64d", i64TotalGB));
这会以不打算使用的方式使用
_T
宏。它应该包装单个字符串文本。在代码中,它包装了第二个参数。 -
printf("totalSpace contains: %s", totalSpace);
这假定使用 ANSI 编码的字符串,但传递一个
CString
对象,该对象可以存储 ANSI 和 Unicode 编码的字符串。
建议的做法是完全删除泛型文本映射,转而在整个1中使用 Unicode(即 Windows 上的 UTF-16LE(。泛型文本映射在 20 年前是相关的,以便于将 Win9x 代码移植到基于 Windows NT 的产品。
为此
- 选择
CStringW
而不是CString
。 - 删除所有出现的
_T
、TEXT
和_TEXT
,并用L
前缀替换它们。 - 使用 Windows API、CRT 和 C++ 标准库的宽字符版本。
固定代码如下所示:
__int64 i64TotalGB;
CStringW totalSpace; // Use wide-character string
i64TotalGB = 150;
printf("disk space: %I64d GBn", i64TotalGB);
totalSpace.Format(L"%I64d", i64TotalGB); // Use wide-character string literal
wprintf(L"totalSpace contains: %s", totalSpace.GetString()); // Use wide-character library
在不相关的说明中,虽然在变量参数列表中传递CString
对象代替字符指针在技术上是安全的,但这是一个实现细节,并且没有正式记录工作。调用CString::GetString((如果你关心正确的代码。
1除非有正当理由使用使用char
作为其基础类型的字符编码(如 UTF-8 或 ANSI(。在这种情况下,您仍应通过使用CStringA
来明确说明它。
试试这个
totalSpace.Format(_T("%I64d"), i64TotalGB);
- C++ MFC Libraries in Travis CI
- 从 bmp 文件数据创建 MFC CBitmap
- 如何在 MFC 中显示文件的所有行
- 目录删除 MFC 的问题
- MFC:如何设置CEdit框的焦点?
- MFC 中的抗锯齿
- 双击更改 mfc 中列表控件中的行的颜色
- C++MFC编辑框处理双击
- C++ MFC CObject 派生类摘要?
- 如何在 MFC 对话框中使用 OnDraw
- 在 1 个服务器 n 客户端套接字 C++ MFC 应用程序中更新数据的客户端
- MFC:你能在CDateTimeCtrl中改变自旋的加速度吗?
- MFC:我们如何轻松地从CTreeCtrl切换到CTreeView?
- __int64 CString 返回错误的值 - C++ MFC
- 如何在MFC中的静态文本控件上插入图标?
- 使用 MFC 的表/网格
- MFC 中的窗口消息管理:添加基类调用是否是强制性的?
- MFC/C++ ComboBox:禁用下拉列表关闭和打开(UI 冻结)的绘制
- C++ MFC 跟踪事件调用
- 如何在 MFC 应用程序中启动 ZeroMQ 线程?