在哪里可以找到off_t类型的完整定义?


75

我正在使用TCP从客户端向服务器发送文件。为了标记文件的结尾,我想在实际数据之前发送文件大小。因此,我使用stat系统调用来查找文件的大小。这是类型off_t。我想知道它占用了多少字节,以便可以在服务器端正确读取它。它在中定义 <sys/types.h>。但是我不明白这个定义。它只是定义__off_t or _off64_toff_t。在哪里找__off_t__头文件中大多数内容的前缀也是约定,当我阅读头文件以更好地理解它时,这使我感到恐惧。如何更好地读取头文件?


6
开头的所有__内容保留供实现使用(除非标准定义了它的含义,如__func____FILE__)。间接级别使实现可以定义自己的类型,__off_t而不会干扰您可以合法做的任何事情。然后可以更好地隐藏标头的特定于平台的位(例如,源代码的单个副本可以在单个计算机上处​​理32位和64位编译)。读取标准标头是一项繁重的工作,因为存在许多相互关联的定义。
乔纳森·莱夫勒

Answers:


93

由于此答案仍被投票赞成,我想指出,您几乎永远不需要查看头文件。如果您想编写可靠的代码,则可以通过查看标准来更好地服务。比“如何off_t在我的计算机上定义”更好的问题是“off_t标准如何定义?”。遵循标准意味着您的代码将在今天和明天在任何计算机上运行。

在这种情况下,off_tC标准没有定义。它是POSIX标准的一部分,您可以在此处浏览

不幸的是,off_t定义不是很严格。我所能定义的只是在以下页面上sys/types.h

blkcnt_t并且off_t应为带符号整数类型。

这意味着您无法确定它的大小。如果您使用的是GNU C,则可以使用下面答案中的说明来确保它是64位。或者更好的是,您可以先将其转换为标准定义的尺寸,然后再将其放在网上。这就是Google的协议缓冲区之类的项目的工作方式(尽管这是C ++项目)。


因此,我认为“在头文件的哪里可以找到定义”不是最好的问题。但是,出于完整性考虑,以下是答案:

在我的机器上(以及大多数使用glibc的机器上),您会在其中找到定义bits/types.h(如顶部的注释中所述,从不直接包含此文件),但是一堆宏中却掩盖了一点。尝试分解它们的另一种方法是查看预处理器输出:

接着:

但是,如果您想知道某物的大小,可以随时使用sizeof()运算符。

编辑:刚刚看到了您有关的部分问题__这个答案有很好的讨论。关键在于,以开头的名称__是为实现保留的(因此,您不应以开头自己的定义__)。


我使用on_t的大小。在我的机器(客户端)上,它是4个字节。因此,我可以代表的最大文件大小为2 ^ 32字节。在这种特殊情况下,这是否必须与我服务器上的off_t大小匹配。我不应该相信。
FourOfAKind 2012年

1
的确off_t可以在不同的机器(或编译器)上使用不同的大小。请注意,在GCC中,您可以-D_FILE_OFFSET_BITS=64用来获取8个字节off_tsize_t定义。
蒂莫西·琼斯

好的,那么服务器应该寻找前4个字节还是前8个字节才能获取文件的长度。
FourOfAKind 2012年

好,我知道了。我应该使用较大的值(例如long long),该值应确保在两台计算机上都相同,然后向上强制将其发送给服务器。
FourOfAKind 2012年

4
不能保证两台机器上的long long大小相同-确切的大小没有标准化。
蒂莫西·琼斯 Timothy Jones)

44

正如《 GNU C库参考手册》所说

off_t
    This is a signed integer type used to represent file sizes. 
    In the GNU C Library, this type is no narrower than int.
    If the source is compiled with _FILE_OFFSET_BITS == 64 this 
    type is transparently replaced by off64_t.

off64_t
    This type is used similar to off_t. The difference is that 
    even on 32 bit machines, where the off_t type would have 32 bits,
    off64_t has 64 bits and so is able to address files up to 2^63 bytes
    in length. When compiling with _FILE_OFFSET_BITS == 64 this type 
    is available under the name off_t.

因此,如果您想要一种可靠的方式来表示客户端和服务器之间的文件大小,则可以:

  1. 相应地使用off64_t类型和stat64()功能(因为它填充了结构stat64,其中包含off64_t类型本身)。类型off64_t保证在32位和64位计算机上的大小相同。
  2. 正如前面所提到的编译代码-D_FILE_OFFSET_BITS == 64和使用通常的off_tstat()
  3. 兑换 off_tint64_t固定大小的类型(C99标准)。 注意:(我的书《 C in a Nutshell》说这是C99标准,但在实现上是可选的)。最新的C11标准说:
7.20.1.1 Exact-width integer types

    1 The typedef name intN_t designates a signed integer type with width N ,
    no padding bits, and a two’s complement representation. Thus, int8_t 
    denotes such a signed integer type with a width of exactly 8 bits.
    without mentioning.

关于实现:

7.20 Integer types <stdint.h>

    ... An implementation shall provide those types described as ‘‘required’’,
    but need not provide any of the others (described as ‘‘optional’’).
    ...
    The following types are required:
    int_least8_t  uint_least8_t
    int_least16_t uint_least16_t
    int_least32_t uint_least32_t
    int_least64_t uint_least64_t
    All other types of this form are optional.

因此,通常,C标准不能保证具有固定大小的类型。但是大多数编译器(包括gcc)都支持此功能。


8

如果您在跟踪定义时遇到困难,则可以使用编译器的预处理输出,该输出将告诉您所有需要了解的内容。例如

如果查看完整的输出,甚至可以看到确切的头文件位置和定义它的行号:

...


5

如果您正在编写可移植的代码,则答案是“您无法分辨”,好消息是您不需要。您的协议应包括将大小写为(例如)“ 8个八位字节,大端格式”(理想情况下,检查实际大小是否适合8个八位字节。)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.