21

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?

user1290696
  • 489
  • 1
  • 4
  • 10

5 Answers5

7

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

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • Where does POSIX put a requirement for `st_size` for regular files? – user1290696 Sep 05 '12 at 07:24
  • 1
    POSIX requires `st_size` to reflect the file's actual size for regular files, and requires it to reflect the symbolic link length for symlinks. The requirement for symlinks is documented with `stat`; the requirement for regular files seems to be omitted there, but the documentation for `sys/stat.h` says that for regular files, `st_size` is the size of the file in bytes. – R.. GitHub STOP HELPING ICE Sep 05 '12 at 07:31
6

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).

supercat
  • 77,689
  • 9
  • 166
  • 211
2

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.

alk
  • 69,737
  • 10
  • 105
  • 255
1

I think some fseek function in POSIX need to accept negative as offset.

wbao
  • 205
  • 1
  • 5
0

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).

niqueco
  • 2,261
  • 19
  • 39
  • 2
    Note that `lseek`'s argument is a *relative* file position (offset), which is the main reason `off_t` needs to be signed. And the fact that you can only seek to positive absolute file positions imposes a restriction that files cannot be larger than the maximum value of the (signed) type `off_t`, so there's no use in having a `filesize_t` that's unsigned to hold larger values. – R.. GitHub STOP HELPING ICE Sep 05 '12 at 07:13