【问题标题】:ostream showbase does not show "0x" for zero valueostream showbase 不显示“0x”为零值
【发布时间】:2010-07-17 23:27:37
【问题描述】:

PSPS:(预先编写好的后置脚本)
刚刚想到一个更有先见之明的问题将包括以下概念:对于零值整数,这种不显示“0x”(showbase)是一种标准行为,还是只是我的 MinGW 实现的一个怪癖?

这一切都始于一个愉快的星期天早上...我想以十六进制表示形式转储一些句柄,并以一致的格式化方式。
我想要一个领先的 0x 和一个固定宽度,但事实证明,使用预期的流操纵器这是难以捉摸的。
我发现这样做的唯一方法是将句柄转换为无符号长整数。 这似乎有点不合理,我希望我不是唯一一个想要这个的人。
我在标准十六进制操纵器中遗漏了什么?是因为 void* (HANDLE) 类型只是在 ostream 的正常十六进制处理之外定义的吗?

总结:我不想将 HANDLE 强制转换为它不是的东西。
而且我不想硬编码“0x”前缀。有没有办法使用标准机械手来做到这一点?还是我需要重载 ostream 对 HANDLE 的处理? (但这可能会让我超负荷!)

这是我的测试代码(及其输出)。
我用过'。作为填充字符,为清楚起见,(我实际上将使用'0')

HANDLE h; 
ULONG ul; 
int iH = sizeof(h); // how many bytes to this void* type.
int iW = iH*2;      // the max number of hex digits (width).
int iW2= iW+2;      // the max number of hex digits (+ 2 for showbase "0x").
int iX = 4;         // the number of bits per hex digit.
int ib = iH*8;      // the max number bits in HANDLE (exponent).
int i;
std::cout<<std::setfill('.'); // I actually want '0'; 
                              //   the dot is for display clarity
for( i=0; i<=ib; i+=iX )
{ ul = (pow(2,i)-1);
  h  = (HANDLE)ul;
  std::cout
  <<"//  ul "        <<std::setw(iW2)<<std::hex <<std::showbase  <<std::internal <<ul
  <<"     h "        <<std::setw(iW2) /* hex,showbase,internal have no effect */ <<h
  <<"      I want 0x"<<std::setw(iW) <<std::hex <<std::noshowbase<<std::right    <<(ULONG)h
  <<std::endl;
}

//  ul .........0     h .........0      I want 0x.......0
//  ul 0x.......f     h .......0xf      I want 0x.......f
//  ul 0x......ff     h ......0xff      I want 0x......ff
//  ul 0x.....fff     h .....0xfff      I want 0x.....fff
//  ul 0x....ffff     h ....0xffff      I want 0x....ffff
//  ul 0x...fffff     h ...0xfffff      I want 0x...fffff
//  ul 0x..ffffff     h ..0xffffff      I want 0x..ffffff
//  ul 0x.fffffff     h .0xfffffff      I want 0x.fffffff
//  ul 0xffffffff     h 0xffffffff      I want 0xffffffff

【问题讨论】:

  • 您是否尝试过将您的句柄转换为 void*?正常的 ostream 应该在输入指针时打印出地址。强制转换为 unsigned long 是不好的,因为您不能总是依赖它与指针类型的大小相同。
  • 谢谢 George.. HANDLE 是 void* 的类型。我刚刚尝试将 HANDLE 显式地键入 (void*),结果是一样的。 主要的事情我在这里试图避免铸造.. 我更喜欢使用标准机械手。 (我的第三个示例专栏使用演员表)。

标签: c++ formatting stream manipulators


【解决方案1】:

我在https://bugzilla.redhat.com/show_bug.cgi?id=166735 上找到了这个 - 这是直接从那里复制/粘贴的。

对我来说听起来不像是一个错误。 ISO C++98, 22.2.2.2.2/10 说 std::showbase 意味着前置 #printf 转换 限定符。 22.2.2.2.2/7 说 std::hex 表示 printf 转换说明符是 %X。 所以行为是恕我直言,要求与 printf ("%#x", 0); 相同。 但是http://www.opengroup.org/onlinepubs/009695399/functions/fprintf.html 说: “对于 x 或 X 转换说明符,非零结果应为 0x(或 0X) 前缀。” 在 ISO C99, 7.19.6.1(6) 中也是如此: “对于 x(或 X)转换,非零结果的前缀为 0x(或 0X)。”

所以这听起来像 C++98 标准(通过说'让它像 C 的 printf("%#x", 0)')需要你看到的这种愚蠢的行为。获得所需内容的唯一方法是摆脱 std::showbase 并显式输出 0x 。对不起。

【讨论】:

  • 再次感谢乔治。 “愚蠢的行为” :) 我喜欢它。似乎不可能抑制“0x”。它不受 hex/dec/oct 和 showbase/noshowbase 的影响。此外,operator>(void*) .. 我会在时间允许的情况下研究它。 C'est la vie...
  • @orthogonal: 转换成 intptr_t 怎么样?
  • 很好的答案。谢谢!
【解决方案2】:

当值为零时 std::showbase 没有“0x”这一事实有时很烦人,但这就是它的定义方式,您对此无能为力,除了:

std::cout << "0x" << .....

“0x”与其余部分之间的差距是可以修复的,但不是很容易猜到。试试

std::cout << std::hex << std::showbase << std::setw(8) << std::setfill('0') << h;

【讨论】:

  • 谢谢迈克尔......至少我现在知道我没有错过一些明显的东西,它的功能只是“看起来”......我已经设法绕过它(现在),通过强制转换为无符号整数,使用 sizeof() 检查(我在乔治的回答中评论过)
猜你喜欢
  • 1970-01-01
  • 2015-11-20
  • 2020-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多