为什么许多在线评测机建议不要使用%lld
格式符在C++中读写64位整数?
是更倾向于使用cin
、cout
流还是%I64d
格式符呢?
为什么许多在线评测机建议不要使用%lld
格式符在C++中读写64位整数?
是更倾向于使用cin
、cout
流还是%I64d
格式符呢?
我认为答案与%lld
有关,表示long long
十进制数,但它不能保证是64位的。例如,在某些系统上,它可能是128位。(尽管如果变量是long long
而不是uint64_t
,那么我希望使用%lld
- 否则将出现另一种错误)
不幸的是,printf
和scanf
及其类似函数的设计使得编译器实现和格式必须匹配。
显然,cout
和cin
是安全的,因为编译器会自动选择正确的输出和输入转换。
这也可能与“在线评测”使用的编译器有关-我认为Microsoft编译器在某个时间支持了64位整数,但不支持long long
,因此没有%lld
,但却有%l64d
。
cin
和cout
的<<
和>>
运算符都有适用于每个整数和浮点数类型的版本。如果您使用cin
和cout
,只需执行cin >> integer_variable
或cout << integer_variable
即可,cin
和cout
会自动处理。
如果您使用某种形式的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位更长。如果您的编译器提供另一种类型__int64
或int64_t
(以及相同的无符号版本),它恰好为64位,则不应混合和匹配其类型说明符,因为这经常被错误地执行。仍然应该使用"%lld"
和"%llu"
来表示long long
和unsigned long long
,以及适用于__int64
的任何内容(也许是"%I64d"
),以及适用于int64_t
的PRId64
宏。
基本上,您应该避免使用类似于printf()
的函数,或者非常小心地使用它们。
问题1的答案:
因为它们在后台使用编译器。GNU
支持%l64d
,而MS
支持%lld
和%l64d
。
问题2的答案:
是的,最好使用cin
、cout
。因为它们内部自行决定。
long long
是否是64位长,例如? - user529758printf
不是类型安全的。如果用户传递了其他类型,那么它会给您带来未定义的行为。而使用cout
,编译器会根据类型适当地选择一个有效的重载版本或返回错误,没有未定义的行为。 - Alok Save%l64d
是格式说明符,它告诉编译器作为参数传递的数字将是64
位长。但并不一定在每个环境中用于存储这些数字的long long
类型实际上是64
位的。在格式说明符和实际传递给printf
的数据之间存在任何不匹配都会导致未定义行为。因此,这种类型不安全的行为可能会对您造成严重影响。 - Alok Save