为什么在C++中使用cin、cout或%I64d比%lld指示符更受欢迎?

23

为什么许多在线评测机建议不要使用%lld格式符在C++中读写64位整数

是更倾向于使用cincout流还是%I64d格式符呢?


8
因为你不能确定 long long 是否是64位长,例如? - user529758
2
因为使用 printf 不是类型安全的。如果用户传递了其他类型,那么它会给您带来未定义的行为。而使用 cout,编译器会根据类型适当地选择一个有效的重载版本或返回错误,没有未定义的行为。 - Alok Save
@AlokSave 但为什么 %I64d 被优先选择而不是 %lld? - Rishabh
https://dev59.com/pEbRa4cB1Zd3GeqP4_D3 - Roman Saveljev
第一个评论已经回答了你的问题。我的评论回答了第二个问题。更具体地说,%l64d是格式说明符,它告诉编译器作为参数传递的数字将是64位长。但并不一定在每个环境中用于存储这些数字的long long类型实际上是64位的。在格式说明符和实际传递给printf的数据之间存在任何不匹配都会导致未定义行为。因此,这种类型不安全的行为可能会对您造成严重影响。 - Alok Save
3个回答

16

我认为答案与%lld有关,表示long long十进制数,但它不能保证是64位的。例如,在某些系统上,它可能是128位。(尽管如果变量是long long而不是uint64_t,那么我希望使用%lld - 否则将出现另一种错误)

不幸的是,printfscanf及其类似函数的设计使得编译器实现和格式必须匹配。

显然,coutcin是安全的,因为编译器会自动选择正确的输出和输入转换。

这也可能与“在线评测”使用的编译器有关-我认为Microsoft编译器在某个时间支持了64位整数,但不支持long long,因此没有%lld,但却有%l64d


1
我发现了这个链接http://codeforces.com/blog/entry/417#,其中提到: 如果你选择"GNU C++"或"GNU C"选项进行提交,请使用以下代码: printf("%I64d\n",n); 而不是: printf("%lld\n",n);如果你选择"MS C++"选项进行提交,两种变量都可以使用。 - Rishabh
我怀疑这是因为GNU C实际上使用了较旧的MS VC运行时库(因为在Windows上glibc不容易获得)。 - Mats Petersson

5
cincout<<>>运算符都有适用于每个整数和浮点数类型的版本。如果您使用cincout,只需执行cin >> integer_variablecout << integer_variable即可,cincout会自动处理。

如果您使用某种形式的printf()函数,则必须非常小心地传递参数。如果传递给它一个int,则必须同时传递其类型说明符"%d",对于unsigned int,为"%u",对于long,为"%ld",对于unsigned long long,为"%llu",对于size_t,为"%zu"等等。如果传递的类型说明符与整数类型不匹配,则会引发未定义行为。因此,程序可能会打印错误的数字,或者破坏自身,或者挂起,或者崩溃,或者以其他神秘的方式表现不当。

现在,C++11语言标准(以及C99)至少有一种整数类型是64位或更长的,即long long(以及其无符号对应项,unsigned long long)。如果您使用它,则必须意识到它可能比64位更长。如果您的编译器提供另一种类型__int64int64_t(以及相同的无符号版本),它恰好为64位,则不应混合和匹配其类型说明符,因为这经常被错误地执行。仍然应该使用"%lld""%llu"来表示long longunsigned long long,以及适用于__int64的任何内容(也许是"%I64d"),以及适用于int64_tPRId64宏。

基本上,您应该避免使用类似于printf()的函数,或者非常小心地使用它们。


-1

问题1的答案:因为它们在后台使用编译器。GNU支持%l64d,而MS支持%lld%l64d

问题2的答案:是的,最好使用cincout。因为它们内部自行决定。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接