我有一个这样的 API,
class IoType {
......
StatusType writeBytes(......, size_t& bytesWritten);
StatusType writeObjects(......, size_t& objsWritten);
};
我尊敬的团队中的一位高级成员似乎对 size_t 类型有问题,并建议我使用 C99 类型。我知道这听起来很愚蠢,但我总是认为像 uint32_t 和 uint64_t 这样的 c99 类型看起来很难看。我确实使用它们,但只有在确实有必要时才使用它们,例如当我需要序列化/反序列化结构时,我确实想具体说明数据成员的大小。
反对使用 size_t 的理由是什么?我知道它不是真正的类型,但如果我确定,即使 32 位整数对我来说也足够了,并且大小类型似乎适合字节数或对象数等。
I have a API like this,
class IoType {
......
StatusType writeBytes(......, size_t& bytesWritten);
StatusType writeObjects(......, size_t& objsWritten);
};
A senior member of the team who I respect seems to have a problem with the type size_t and suggest that I use C99 types. I know it sounds stupid but I always think c99 types like uint32_t and uint64_t look ugly. I do use them but only when it's really necessary, for instance when I need to serialize/deserialize a structure, I do want to be specific about the sizes of my data members.
What are the arguments against using size_t? I know it's not a real type but if I know for sure even a 32-bit integer is enough for me and a size type seems to be appropriate for number of bytes or number of objects, etc.
发布评论
评论(3)
每当您处理任何类型的序列化(二进制文件、网络等)时,请使用精确大小的类型,例如
uint32_t
。每当您处理内存中对象的大小时,请使用size_t
— 这就是它的用途。所有处理对象大小的函数,例如malloc
、strlen
和sizeof
运算符都是size_t
。如果正确使用
size_t
,您的程序将具有最大程度的可移植性,并且不会在不需要的平台上浪费时间和内存。在 32 位平台上,size_t
将是 32 位 - 如果您使用uint64_t
,则会浪费时间和空间。相反,在 64 位平台上,size_t
将是 64 位 - 如果您使用uint32_t
,您的程序可能会行为不正确(甚至可能崩溃或打开安全性)漏洞)如果它必须处理大于 4 GB 的内存。Use exact-size types like
uint32_t
whenever you're dealing with serialization of any sort (binary files, networking, etc.). Usesize_t
whenever you're dealing with the size of an object in memory—that's what it's intended for. All of the functions that deal with object sizes, likemalloc
,strlen
, and thesizeof
operator allsize_t
.If you use
size_t
correctly, your program will be maximally portable, and it will not waste time and memory on platforms where it doesn't need to. On 32-bit platforms, asize_t
will be 32 bits—if you instead used auint64_t
, you'd waste time and space. Conversely, on 64-bit platforms, asize_t
will be 64 bits—if you instead used auint32_t
, your program could behave incorrectly (maybe even crash or open up a security vulnerability) if it ever had to deal with a piece of memory larger than 4 GB.我认为在不需要序列化值的上下文中使用
size_t
有什么问题。正确使用size_t
还将提高代码在 32 位和 64 位模式下的安全性/可移植性。I can't think of anything wrong in using
size_t
in contexts where you don't need to serialize values. Also usingsize_t
correctly will increase the code's safety/portability across 32 and 64 bit patforms.嗯,用可移植性较差的 C99 固定大小或最小大小无符号类型替换
size_t
(最大可移植性的东西)并不是一个好主意。另一方面,您可以通过使用有符号的 ptrdiff_t 类型来避免很多技术问题(浪费时间)。标准库使用无符号类型只是出于历史原因。它在当时是有意义的,甚至在今天的 16 位架构上也是有意义的,但通常它只是麻烦和麻烦。冗长。
不过,做出这一改变需要一些支持,特别是通用的
size
函数,返回数组或容器大小为ptrdiff_t
。Now, regarding your function signature
这强制调用代码选择写入字节数的类型。
然后,强制使用无符号类型
size_t
,很容易引入错误,例如通过检查它是否小于或大于某个计算量。一个奇怪的例子:std::string("ah").length()
std::string("ah").length()
-5
保证为true
。因此,请这样做……
或者,如果您不想使用异常,
可以将可能的状态枚举为无符号类型或其他类型,因为对状态值的唯一操作将是相等检查,并且可能作为键。
Uhm, it's not a good idea to replace
size_t
(a maximally portable thing) with a less portable C99 fixed size or minimum size unsigned type.On the other hand, you can avoid a lot of technical problems (wasted time) by using the signed
ptrdiff_t
type instead. The standard library’s use of unsigned type is just for historical reasons. It made sense in its day, and even today on 16-bit architectures, but generally it is nothing but trouble & verbosity.Making that change requires some support, though, in particular a general
size
function that returns array or container size asptrdiff_t
.Now, regarding your function signature
This forces the calling code’s choice of type for the bytes written count.
And then, with unsigned type
size_t
forced, it is easy to introduce a bug, e.g. by checking if that is less or more than some computed quantity.A grotesque example:
std::string("ah").length() < -5
is guaranteedtrue
.So instead, make that …
or, if you do not want to use exceptions,
It is OK to have an enumeration of possible statuses as unsigned type or as whatever, because the only operations on status values will be equality checking and possibly as keys.