st_size
is defined as being an off_t
.
off_t
is defined as being a signed integer type.
Why is st_size
defined as a signed type? Can it be negative? What does it mean if it is negative?
The best reason I can think of is to avoid introducing an unsigned version of off_t
as an extra type; POSIX already has a ridiculous abundance of integer types with similar uses.
Aside from that, being able to store -1 in st_size
when size is not a concept that makes sense is probably useful; I'm not sure if any implementations do this, and I can't find where POSIX puts any requirements on the contents of st_size
except for regular files and symlinks...
Under C's promotion rules, expressions combining different sizes of signed types will behave the same arithmetically-correct fashion regardless of the sizes involved provided that none of the intermediate computations overflow. Adding unsigned types, however, will make code's behavior much more dependent on integer sizes.
Given:
int test_size(off_t x, long y, long long z)
{
return x-y > z;
}
If off_t
were unsigned, then depending upon its size it could cause y
to get
promoted to unsigned long
, with computation performed on that type, which would then get promoted to signed long long
and compared with z
using a signed comparison, or it could cause z
to get promoted to unsigned long long
, in which case the overall comparison would be done in unsigned fashion. It would also be possible (though not necessarily likely) that off_t
could be small enough (and/or long
big enough) that y
gets subtracted using signed arithmetic.
Quantities that might large enough to require something at least as big as int
, even if they will never be negative, should generally be represented by unsigned types only if there is reason to believe they won't fit in a particular signed type but would certainly fit in its unsigned counterpart. Such situations aren't terribly common, but existed with size_t on 16-bit systems (it was architecturally impossible for a single object to exceed 64K, but objects over 32K were commonplace). Such a scenario would seem less compelling in a file-system interface (if 32-bit signed isn't enough, 32-bit unsigned probably won't be enough for very long either).
off_t
defines offsets in a file, which could be equal to the file's size, but also can be negative, for example if seeking backwards.
From this relation between offset and size, a file's size has the same type as a file offset. Anyhow, a file size shall not be negative.
off_t
is used to handle file offsets in many functions. Some functions use the special value -1 (e.g. lseek
does that to tell you an error has occurred). Many other data types are signed in UNIX for accommodating -1 values (e.g. time_t
).