作者:大东o世界 | 来源:互联网 | 2023-02-01 11:28
刚刚遇到一些(非常)遗留代码(最初编写为C但现在编译为C++)并使用宽度说明符将零填充字符串
void main()
{
unsigned long val = 2413;
printf("V1: %08lu \n", val);
printf("V2: %8.8lu \n", val);
}
结果是一样的
V1: 00002413
V2: 00002413
那么为什么要使用V2呢?从昔日开始,它是std lib的遗留方面吗?
编译器详细信息:用于x86的Microsoft(R)C/C++优化编译器版本19.10.25019
1> AnT..:
对于无符号整数类型,没有区别.对于有符号整数类型的负值,您将看到不同的输出
long val = -2413;
printf("V1: %08ld\n", val);
printf("V2: %8.8ld\n", val);
V1: -0002413
V2: -00002413
该.8
部分%8.8ld
指定显示的最小数字位数.并且该-
标志不被视为数字.因此,第二个版本需要始终打印8位数.如果值为负,则-
符号将别无选择,只能成为打印的第9个字符,因此违反了请求的字段宽度8.
该%08ld
版本不需要打印至少8位数,这就是为什么-
符号占据字段宽度8 内的一个字符,并且只打印7位数字.
http://coliru.stacked-crooked.com/a/fc9022cc0ef3e097
@gsamaras:是的.`.8`部分指定*出现的最小位数*.这意味着您将始终看到8位数字.`-`不计算在内.这允许它突破8个字符字段.在第一个版本中没有"最低"要求,这就是为什么`-`吃掉一个空格并导致输出的数字减少.
2> Jonathan Lef..:
正如我在评论中所指出的,对于字符串,%8s
和之间存在差异%8.8s
- 如果字符串长于,则后者会截断8
.还有另一个不同之处; 0
不是有效的修饰符%s
.与... %8.8lu
没有什么不同%.8lu
; %.8lu
和之间没有太大区别%08lu
,虽然0
年龄较大,但是.
被添加到了C90(这些日子已经很老了).但是,当值为负时,%.8ld
和之间存在差异%08ld
.
下面是一些代码,用于说明有printf()
符号和无符号值的整数格式的一些变幻莫测.请注意,如果你有(%8.6lu
而不是%8.8lu
签名),你会得到有趣的差异.
#include
static void test_ul(void)
{
char *fmt[] =
{
"%08lu",
"%8.8lu",
"%.8lu",
"%8.6lu",
"%6.8lu",
};
enum { NUM_FMT = sizeof(fmt) / sizeof(fmt[0]) };
unsigned long val[] = { 2413LU, 234512349LU };
enum { NUM_VAL = sizeof(val) / sizeof(val[0]) };
for (int i = 0; i
输出(macOS Sierra 10.12.5上的GCC 7.1.0):
%08lu: [00002413]
%08lu: [234512349]
%8.8lu: [00002413]
%8.8lu: [234512349]
%.8lu: [00002413]
%.8lu: [234512349]
%8.6lu: [ 002413]
%8.6lu: [234512349]
%6.8lu: [00002413]
%6.8lu: [234512349]
%08ld: [00002413]
%08ld: [-0002413]
%08ld: [234512349]
%08ld: [-234512349]
%8.8ld: [00002413]
%8.8ld: [-00002413]
%8.8ld: [234512349]
%8.8ld: [-234512349]
%.8ld: [00002413]
%.8ld: [-00002413]
%.8ld: [234512349]
%.8ld: [-234512349]
%8.6ld: [ 002413]
%8.6ld: [ -002413]
%8.6ld: [234512349]
%8.6ld: [-234512349]
%6.8ld: [00002413]
%6.8ld: [-00002413]
%6.8ld: [234512349]
%6.8ld: [-234512349]
3> gsamaras..:
当unsigned long
你在ref中读到时,这两个在与(/整数)一起使用时是等价的.
printf("V1: %08lu \n", val);
0
当指定填充时,flag将使用零(0)而不是空格填充数字(请参阅width子说明符).
8
将是number
"要打印的最小字符数.如果要打印的值小于此数字,则结果将填充空格.即使结果较大,也不会截断该值."
现在这个:
printf("V2: %8.8lu \n", val);
将保持8
as 的效果number
,但将添加.8
,如.number
"对于整数说明符(d,i,o,u,x,X):precision指定要写入的最小位数.如果要写入的值更短比这个数字,结果用前导零填充.即使结果更长,该值也不会被截断.精度为0意味着没有为值0写入字符."
PS:标准C++应该发出诊断错误:
prog.cc:3:11: error: '::main' must return 'int'
void main()
^
然而,即使是Stroustrup本人也说这"不是也不是C++,甚至也不是C".