哪里可以findoff_ttypes的完整定义?

我使用TCP将文件从客户端发送到服务器。 要标记文件的结尾,我希望在实际数据之前发送文件大小。 所以我使用stat系统调用来查找文件的大小。 这是typesoff_t 。 我想知道它占用了多less字节,以便我可以在服务器端正确读取它。 它在<sys/types.h>定义。 但是我不明白这个定义。 它只是将__off_t or _off64_t定义为off_t 。 在哪里寻找__off_t ? 也是约定, __是头文件中的大部分事物的前缀,当我阅读头文件以更好地理解时,会吓到我。 如何更好地读取头文件?

 #ifndef __off_t_defined # ifndef __USE_FILE_OFFSET64 typedef __off_t off_t; # else typedef __off64_t off_t; # endif # define __off_t_defined #endif 

由于这个答案仍然被投票,我想指出,你几乎不需要看头文件。 如果你想编写可靠的代码,通过查看标准,你会更好地服务。 比“在我的机器上如何定义off_t ”更好的问题是“标准怎么定义off_t ?”。 遵循标准意味着您的代码将在今天和明天在任何机器上运行。

在这种情况下, off_t不是由C标准定义的。 这是POSIX标准的一部分, 您可以在这里浏览 。

不幸的是, off_t没有被严格定义。 所有我能find的定义它是在sys/types.h的页面上:

blkcnt_toff_t应该是有符号整数types。

这意味着你不能确定它有多大。 如果您使用的是GNU C,则可以使用下面答案中的说明来确保它是64位。 或者更好的是,您可以在将其放置在电线上之前将其转换为标准定义的尺寸。 这就是Google的Protocol Buffers这样的项目(尽pipe这是一个C ++项目)。


所以,我认为“我在哪里可以find我的头文件中的定义”不是最好的问题。 但是,为了完整性,答案是:

你可以在bits/types.hfind这个定义(就像上面的注释一样,不要直接包含这个文件),但是在一堆macros中它会被遮住一点。 试图解开它们的另一种方法是查看预处理器输出:

 #include <stdio.h> #include <sys/types.h> int main(void) { off_t blah; return 0; } 

接着:

 $ gcc -E sizes.c | grep __off_t typedef long int __off_t; .... 

但是,如果您想知道某个东西的大小,则可以始终使用sizeof()运算符。

编辑:刚才看到你的关于__的问题的一部分。 这个答案有一个很好的讨论 。 关键是,以__开头的名字是为实现保留的(所以你不应该用__开始你自己的定义)。

正如“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_ttypes和stat64()函数(因为它填充结构stat64 ,其中包含off64_ttypes本身)。 键入off64_t在32位和64位计算机上保证相同的大小。
  2. 如前所述,使用-D_FILE_OFFSET_BITS == 64编译代码 ,并使用通常的off_tstat()
  3. off_t转换为固定大小(C99标准)的int64_ttypes。 注意:(我的书“坚果壳中的C”说它是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标准不能保证具有固定大小的types。 但是大多数编译器(包括gcc)都支持这个function。

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

如果在追踪定义时遇到问题,可以使用编译器的预处理输出,它会告诉你所有你需要知道的信息。 例如

 $ cat test.c #include <stdio.h> $ cc -E test.c | grep off_t typedef long int __off_t; typedef __off64_t __loff_t; __off_t __pos; __off_t _old_offset; typedef __off_t off_t; extern int fseeko (FILE *__stream, __off_t __off, int __whence); extern __off_t ftello (FILE *__stream) ; 

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

 # 132 "/usr/include/bits/types.h" 2 3 4 typedef unsigned long int __dev_t; typedef unsigned int __uid_t; typedef unsigned int __gid_t; typedef unsigned long int __ino_t; typedef unsigned long int __ino64_t; typedef unsigned int __mode_t; typedef unsigned long int __nlink_t; typedef long int __off_t; typedef long int __off64_t; 

 # 91 "/usr/include/stdio.h" 3 4 typedef __off_t off_t;