DbgPrint 输出
1) 直接打印字符串。
DbgPrint(“Hello World!”);
2) 空结尾的字符串,你可以用普通得C语法表示字符串常量
char variable_string[] = “Hello World”;
DbgPrint(“%s”, variable_string);
3) 空结尾的宽字符串(WCHAR类型)
WCHAR string_w[] = L“Hello World!”;
DbgPrint(“%ws”, string_w);
或者
DbgPrint(“%S”, string_w);
4)Unicode串,由UNICODE_STRING结构描述,包含16位字符。
typedef struct _UNICODE_STRING{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
}UNICODE_STRING , *PUNICODE_STRING;
UNICODE_STRING string_unicode = L”Hello World!”;
DbgPrint(“%wZ\n”, &string_unicode);
5) ANSI串,由ANSI_STRING结构描述,包含8位字符。
typedef struct _STRING{
USHORT Length;
USHORT MaximumLength;
PCHAR Buffer;
}STRING, *PANSI_STRING;
STRING bar;
或者:ANSI_STRING bar;
RtlInitAnsiString(&bar, ”Hello World!”);
DbgPrint(“%wZ\n”, &bar);
DebugPrint格式说明符
符号 格式说明符 类型
%c, %lc ANSI字符 char
%C, %wc 宽字符 wchar_t
%d, %i 十进制有符号整数 int
%D 十进制_int64 _int64
%L 十六进制的LARGE_INTEGER LARGE_INTEGER
%s, %ls NULL终止的ANSI字符串 char*
%S, %ws NULL终止的宽字符串 wchar_t*
%Z ANSI_STRING字符串
%wZ UNICODE_STRING字符串
%u 十进制的ULONG ULONG
%x 小写字符十六进制的ULONG ULONG
%X 大写字符十六进制的ULONG ULONG
%p 指针Pointer 32/64位
根据DDK上说明,Unicode格式(%C, %S, %lc, %ls, %wc, %ws, and %wZ)只能在 IRQL = PASSIVE_LEVEL时才能使用.
在Vista下模式DbgPrint的输出信息是无法输出到WinDbg中的,这是因为Vista下引入了新的函数DbgPrintEx (DbgPrint实际上调用这个函数),这个函数可以控制输出的Level(这下不用自己做这样的工作了)。但是默认的,Vista下DbgPrint 输出的信息在WinDBG中是无法生效的。可以按一下方法来使它生效:
打开注册表到这个路径:HKLM\SYSTEM\CCS\Control\Session Manager\Debug Print Filter
修改Default值为0F,重启即可。
===========================================================
在C/C++中,64为整型一直是一种没有确定规范的数据类型。现今主流的编译器中,对64为整型的支持也是标准不一,形态各异。一般来说,64位整型的定义方式有long long和__int64两种(VC还支持_int64),而输出到标准输出方式有printf(“%lld”,a),printf(“%I64d”,a),和cout << a三种方式。
本文讨论的是五种常用的C/C++编译器对64位整型的支持,这五种编译器分别是gcc(mingw32),g++(mingw32),gcc(linux i386),g++(linux i386),Microsoft Visual C++ 6.0。可惜的是,没有一种定义和输出方式组合,同时兼容这五种编译器。为彻底弄清不同编译器对64位整型,我写了程序对它们进行了评测,结果如下表。
变量定义 | 输出方式 | gcc(mingw32) | g++(mingw32) | gcc(linux i386) | g++(linux i386) | MicrosoftVisual C++ 6.0 |
---|---|---|---|---|---|---|
long long | “%lld” | 错误 | 错误 | 正确 | 正确 | 无法编译 |
long long | “%I64d” | 正确 | 正确 | 错误 | 错误 | 无法编译 |
__int64 | “lld” | 错误 | 错误 | 无法编译 | 无法编译 | 错误 |
__int64 | “%I64d” | 正确 | 正确 | 无法编译 | 无法编译 | 正确 |
long long | cout | 非C++ | 正确 | 非C++ | 正确 | 无法编译 |
__int64 | cout | 非C++ | 正确 | 非C++ | 无法编译 | 无法编译 |
long long | printint64() | 正确 | 正确 | 正确 | 正确 | 无法编译 |
上表中,正确指编译通过,运行完全正确;错误指编译虽然通过,但运行结果有误;无法编译指编译器根本不能编译完成。观察上表,我们可以发现以下几点:
- long long定义方式可以用于gcc/g++,不受平台限制,但不能用于VC6.0。
- __int64是Win32平台编译器64位长整型的定义方式,不能用于Linux。
- “%lld”用于Linux i386平台编译器,”%I64d”用于Win32平台编译器。
- cout只能用于C++编译,在VC6.0中,cout不支持64位长整型。
表中最后一行输出方式中的printint64()是我自己写的一个函数,可以看出,它的兼容性要好于其他所有的输出方式,它是一段这样的代码:
{
if (a<=100000000)
printf("%d\n",a);
else
{
printf("%d",a/100000000);
printf("d\n",a0000000);
}
}
这种写法的本质是把较大的64位整型拆分为两个32位整型,然后依次输出,低位的部分要补0。看似很笨的写法,效果如何?我把它和cout输出方式做了比较,因为它和cout都是C++支持跨平台的。首先printint64()和cout(不清空缓冲区)的运行结果是完全相同的,不会出现错误。我的试验是分别用两者输出1000000个随机数,实际结果是,printint64()在1.5s内跑完了程序,而cout需要2s。cout要稍慢一些,所以在输出大量数据时,要尽量避免使用。
//////////////////
d,lx,ld,,lu,这几个都是输出32位的
hd,hx,hu,这几个都是输出16位数据的
hhd,hhx,hhu,这几个都是输出8位的
lld,ll,llu,llx,这几个都是输出64位的
%llx才是64位16进制数
////////////////////////////////////////////////
按照frm 字符串中的格式说明符输出格式化文本格式说明符是标准格式的一个子集
%d--输出有符号十进制整数
%o --输出无符号八进制整数
%x - 输出无符号十六进制整数
%X –除了大写字母使用‘A‘-‘F‘外同 %x
%u - 输出无符号十进制整数
%s – 输出一个以C 中空字符NULL 结束的字符串
%c – 以 ASCII 字符形式输出只输出一个字符
%f – 以小数形式输出浮点数
%S – 输出在FLASH 存贮器中的字符串常量
如果在% 和o 或x 之间指定有一个字符那么就会在开头分别打印0 或
0x 如果在%和一个整数格式字符之间指定有一个l (字母l)字符则输出长整型整数
而不是整型整数
三个版本中支持printf 取决于你的需要和代码的大小要求越高代码越大
基本形: 只支持不带修饰符的 %c, %d, %x, %u, 和 %s 格式说明符
长整形: 支持长整形数修饰符 %ld, %lu, %lx 和 宽度及精度 修饰符
浮点形: 支持全部格式包括%f
%c ANSI字符 char
%C 宽字符 wchar_t
%d,%i 十进制有符号整数 int
%D 十进制__int64 __int64
%I IRP主功能代码和次功能代码 PIRP
%l 十六进制的__int64 __int64
%L 十六进制的LARGE_INTEGER LARGE_INTEGER
%s NULL终止的ANSI字符串 char *
%S NULL终止的宽字符串 wchar_t *
%T UNICODE_STRING PUNICODE_STRING
%u 十进制的ULONG ULONG
%x 十六进制的ULONG ULONG