简体   繁体   English

c和perl之间的printf差异

[英]printf difference between c and perl

In C: 在C中:

printf ("%u", 17860374324089702869);

prints "3336554965" (this is the answer I want!) 打印“ 3336554965”(这是我想要的答案!)

In perl, the same line of code prints "17860374324089702869". 在perl中,同一行代码显示为“ 17860374324089702702”。

How can I get perl to produce "3336554965" from "17860374324089702869". 我怎样才能使perl从“ 17860374324089702869”中产生“ 3336554965”。

My gut says this is 64-bit vs 32-bit issue, but it does not appear that the perl statement is doing anything at all to the number. 我的直觉说这是64位与32位的问题,但似乎perl语句根本没有对数字做任何事情。

In C, printf %u takes an unsigned int . 在C中, printf %u接受一个unsigned int Whether that is a 32-bit or 64-bit value or something different entirely depends on your C implementation. 这是32位还是64位值还是完全不同的值取决于您的C实现。 The standard only requires that int be at least 16 bits wide. 该标准仅要求int至少为16位宽。 (Since the value you're passing in your example doesn't fit in an unsigned int , I'm pretty sure your code has undefined behavior: You're not passing an unsigned int to %u as it expects you to.) (由于您在示例中传递的值不适合unsigned int ,因此我很确定您的代码具有未定义的行为:您没有像期望的那样将unsigned int传递给%u 。)

In Perl, %u converts its argument to an unsigned integer. 在Perl中, %u将其参数转换为无符号整数。 The width of this integer depends on how Perl was compiled; 该整数的宽度取决于Perl的编译方式。 it is normally either a 32-bit or 64-bit type. 它通常是32位或64位类型。 You can query the configuration details for your perl by running perl -V:uvsize (the size of Perl's unsigned integer type in bytes) and perl -V:uvtype (the corresponding C type). 您可以通过运行perl -V:uvsize (Perl的无符号整数类型的大小(以字节为单位))和perl -V:uvtype (对应的C类型)来查询perl的配置详细信息。

If you want to explicitly truncate your value to 32 bits, the easiest way is probably to apply a bit mask: 如果要将值显式地截断为32位,最简单的方法可能是应用位掩码:

use constant { UINT32_MAX => 0xffff_ffff };
print 17860374324089702869 & UINT32_MAX, "\n";

Then you don't really need printf either. 然后,您实际上也不需要printf

There's no such unsigned 32-bit integer in Perl. Perl中没有这样的无符号32位整数。 The 17860374324089702869 become 3336554965 in C is because unsigned 32-bit integer has a range 0 to 4294967295, when there's overflow occur, the integer would came up from the lower bound and vice versa 17860374324089702869变成C中的3336554965是因为无符号的32位整数的范围为0到4294967295,当发生溢出时,该整数将从下限出现,反之亦然

eg 例如

unsigned int a = 4294967296 // will be 0 because unsigned integer upper limit is 4294967295

So you only have to module it with 4294967296 because there's 4294967296 numbers from 0 to 4294967295 因此,您只需用4294967296对其进行模块化,因为从0到4294967295之间有4294967296个数字

#!/usr/bin/perl

printf "%09u", 17860374324089702869 % 4294967296

This is generally not about Perl's printf / sprintf , but about how Perl stores integers and passes integers to functions. 这通常与Perl的printf / sprintf无关,而与Perl如何存储整数并将整数传递给函数有关。 As mentioned in other responses, there is no 32-bit integer type in Perl. 如其他响应中所述,Perl中没有32位整数类型。

Basically, you need to strip the half of your 64-bit integer to make it 32-bit. 基本上,您需要剥离64位整数的一半以使其成为32位。 To do this, just use binary & : 为此,只需使用二进制&

perl -e 'printf("%09u\n", 17860374324089702869 & 0xffffffff);'
3336554965

Here, the & operation leaves bits of the lower 4 bytes unchanged, but sets bits of the higher 4 bytes to zeros. 在此, &操作将低4个字节的位保持不变,但是将高4个字节的位设置为零。

The C language has a plethora of numeric data types (and sizes). C语言具有大量的数字数据类型(和大小)。 Perl has 3 type of data -- " scalars, arrays of scalars, and associative arrays of scalars ", Perl具有3种类型的数据-“ 标量,标量数组和标量的关联数组 ”,

In Perl, scalar values are polymorphic, so the value 17860374324089702869 can be treated as a string or a number, depending on how it is used. 在Perl中,标量值是多态的,因此根据使用方式,可以将值17860374324089702869视为字符串或数字。 When used in a printf statement, it treated as the number 17860374324089702869 and printed as such. 在printf语句中使用时,将其视为编号17860374324089702869,并按此方式打印。

In C, an unsigned integer is treated as an integer number in a range specified by the word size on the architecture you are compiling the program for. 在C语言中,将无符号整数视为在要为其编译程序的体系结构上由字长指定的范围内的整数。 You should have received warning when you compiled. 编译时应该已经收到警告。 When I compiled the above statement with -Wall, here is the warning I got: 当我使用-Wall编译以上语句时,这是我得到的警告:

warning: format '%u' expects argument of type 'unsigned int', but argument 2 has type '__int128' [-Wformat=] 警告:格式'%u'期望类型为'unsigned int'的参数,但是参数2的类型为'__int128'[-Wformat =]

See this post discussing the maximum integer value that can be count to in Perl. 请参阅这篇文章,讨论可以在Perl中计算的最大整数值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM