Tuesday, February 12, 2008

size_t, ptrdiff_t and off_t

Imagine you are writing a library to be used on all sorts of platforms. In this library you have a vector-like class with an index operator [], let's call this class MyArray. What should be the type of index? int comes to mind, but think again. int is 32 bits on both 64-bit platforms and 32-bit platforms (at least on Linux). This means, even though you can create a MyArray object holding number of objects that is larger than the maximum int, you can't index to portions of it because of your choice of int type. There must be a portable way of resolving this issue.

Say hello to size_t and ptrdiff_t.

size_t is the "the unsigned integer type of of the result of the sizeof operator"
ptrdiff_t is the "signed integer type of the result of subtracting two pointers"

These two types are not supposed to be same size all the time, but mostly on all systems I care about they are. They differ based on 64-bit and 32-bit systems. e.g. on 32-bits they are both 32-bits, but on 64-bits they are 64-bits integers.

How to use these types? size_t can represent the number of items you store in MyArray. ptrdiff_t can be used for iterator arithmetic for MyArray's iterators. For example MyArray may provide random access iterators which should support things like ptr-= where can be negative. To be able to fully use the memory space we have available in any platform ptrdiff_t is the ideal choice for the type of .


What's off_t doing in this post? Well, it is a type used to pass offset to various file related functions, such as ftell etc... In 32-bit systems usually it is declared as 32-bit signed integer, since we might want to give a negative offset compared to current file position. But this prevents us to open files larger than 2GB, or at least we can't we can't read from offsets larger than 2GB. To solve this problem many systems define another type called off64_t and related functions. e.g. in addition to pread, they define pread64. In such systems, we either need to use the regular open function with O_LARGEFILE flag or directly use open64 function.

No comments: