开发者

What are the arguments against using size_t?

开发者 https://www.devze.com 2023-04-07 15:07 出处:网络
I have a API like this, class IoType { ...... StatusType writeBytes(......, size_t& bytesWritten); StatusType writeObjects(......, size_t& objsWritten);

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 t开发者_如何学Goype 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.


Use exact-size types like uint32_t whenever you're dealing with serialization of any sort (binary files, networking, etc.). Use size_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, like malloc, strlen, and the sizeof operator all size_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, a size_t will be 32 bits—if you instead used a uint64_t, you'd waste time and space. Conversely, on 64-bit platforms, a size_t will be 64 bits—if you instead used a uint32_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.


I can't think of anything wrong in using size_t in contexts where you don't need to serialize values. Also using size_t correctly will increase the code's safety/portability across 32 and 64 bit patforms.


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 as ptrdiff_t.


Now, regarding your function signature

    StatusType writeBytes(......, size_t& bytesWritten);

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 guaranteed true.

So instead, make that …

    Size writeBytes(......);

or, if you do not want to use exceptions,

    Size writeBytes(......, StatusType& status );

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号