__int64 到 CString returns 错误值 - C++ MFC
__int64 to CString returns wrong values - C++ MFC
我想将 __int64 变量转换为 CString。代码就是这样
__int64 i64TotalGB;
CString totalSpace;
i64TotalGB = 150;
printf("disk space: %I64d GB\n", 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);
这里:
totalSpace.Format(_T("%I64d", i64TotalGB));
您将 i64TotalGB
作为参数传递给 _T()
macro,而不是将其作为第二个参数传递给 Format()
。
试试这个:
totalSpace.Format(_T("%I64d"), i64TotalGB);
话虽如此,由于 MS 在字符编码方面的混乱 (ha),在这里使用 _T
是不正确的,因为 CString
由 TCHAR
组成,而不是_TCHAR
。所以考虑到这一点,不妨使用 TEXT()
而不是 T()
,因为它依赖于 UNICODE
而不是 _UNICODE
:
totalSpace.Format(TEXT("%I64d"), i64TotalGB);
此外,这一行是错误的,因为它试图将 ATL CString
作为 char*
(a.k.a。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
does not currently support output into a UNICODE stream.", the correct version for this line, that will support characters outside your current code page,是以下列方式调用 wprintf()
:
wprintf("totalSpace contains: %s", totalSpace.GetString());
说了这么多,这里有一个一般性的建议,不管问题背后的直接问题是什么。现在更好的做法完全略有不同,我引用@IInspectable 令人尊敬的回答,说 "generic-text mappings were relevant 2 decades ago".
还有什么选择?在没有足够充分理由的情况下,请尝试明确坚持 CStringW
(A Unicode character type string with CRT support). Prefer the L
character literal over the archaic data/text mappings that depend on whether the constant _UNICODE
or _MBCS
has been defined in your program. Conversely, the better practice would be using the wide-character versions of all API and language library calls, such as wprintf()
而不是 printf()
.
该错误是代码的众多问题的结果,特别是这些 2:
totalSpace.Format(_T("%I64d", i64TotalGB));
这以一种不应该使用的方式使用了 _T
macro。它应该包装单个字符串文字。在代码中它包含了第二个参数。
printf("totalSpace contains: %s", totalSpace);
这假定一个 ANSI 编码的字符串,但传递一个 CString
对象,它可以存储 ANSI 和 Unicode 编码的字符串。
建议的做法是完全放弃 generic-text mappings,转而在整个 1 中使用 Unicode(即 Windows 上的 UTF-16LE)。通用文本映射在 2 年前就已存在,用于简化将 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 GB\n", 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
.
明确说明
我想将 __int64 变量转换为 CString。代码就是这样
__int64 i64TotalGB;
CString totalSpace;
i64TotalGB = 150;
printf("disk space: %I64d GB\n", 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);
这里:
totalSpace.Format(_T("%I64d", i64TotalGB));
您将 i64TotalGB
作为参数传递给 _T()
macro,而不是将其作为第二个参数传递给 Format()
。
试试这个:
totalSpace.Format(_T("%I64d"), i64TotalGB);
话虽如此,由于 MS 在字符编码方面的混乱 (ha),在这里使用 _T
是不正确的,因为 CString
由 TCHAR
组成,而不是_TCHAR
。所以考虑到这一点,不妨使用 TEXT()
而不是 T()
,因为它依赖于 UNICODE
而不是 _UNICODE
:
totalSpace.Format(TEXT("%I64d"), i64TotalGB);
此外,这一行是错误的,因为它试图将 ATL CString
作为 char*
(a.k.a。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
does not currently support output into a UNICODE stream.", the correct version for this line, that will support characters outside your current code page,是以下列方式调用 wprintf()
:
wprintf("totalSpace contains: %s", totalSpace.GetString());
说了这么多,这里有一个一般性的建议,不管问题背后的直接问题是什么。现在更好的做法完全略有不同,我引用@IInspectable 令人尊敬的回答,说 "generic-text mappings were relevant 2 decades ago".
还有什么选择?在没有足够充分理由的情况下,请尝试明确坚持 CStringW
(A Unicode character type string with CRT support). Prefer the L
character literal over the archaic data/text mappings that depend on whether the constant _UNICODE
or _MBCS
has been defined in your program. Conversely, the better practice would be using the wide-character versions of all API and language library calls, such as wprintf()
而不是 printf()
.
该错误是代码的众多问题的结果,特别是这些 2:
totalSpace.Format(_T("%I64d", i64TotalGB));
这以一种不应该使用的方式使用了
_T
macro。它应该包装单个字符串文字。在代码中它包含了第二个参数。printf("totalSpace contains: %s", totalSpace);
这假定一个 ANSI 编码的字符串,但传递一个
CString
对象,它可以存储 ANSI 和 Unicode 编码的字符串。
建议的做法是完全放弃 generic-text mappings,转而在整个 1 中使用 Unicode(即 Windows 上的 UTF-16LE)。通用文本映射在 2 年前就已存在,用于简化将 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 GB\n", 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
.