我正在使用TCP将文件从客户端发送到服务器。为了标记文件的结尾,我想在实际数据之前发送文件大小。所以我使用stat
系统调用来查找文件的大小。这是off_t
类型。我想知道它占用了多少字节,以便我可以在服务器端正确读取它。它在<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
答案 0 :(得分:68)
由于这个答案仍然被投票,我想指出你几乎不需要查看头文件。如果您想编写可靠的代码,那么通过查看标准可以获得更好的服务。比“我的机器上off_t
如何定义”更好的问题是“标准如何定义off_t
?”。遵循标准意味着您的代码将在今天和明天在任何计算机上运行。
在这种情况下,{C}标准未定义off_t
。它是POSIX标准的一部分,you can browse here。
不幸的是,off_t
的定义不是很严格。我可以找到定义它的所有内容都在sys/types.h
的页面上:
blkcnt_t
和off_t
应为有符号整数类型。
这意味着您无法确定它有多大。如果您使用的是GNU C,则可以使用the answer below中的指令确保它是64位。或者更好的是,您可以在将其放入线路之前转换为标准定义的大小。这就是Google Protocol Buffers等项目的工作方式(虽然这是一个C ++项目)。
所以,我认为“我在哪里可以找到头文件中的定义”并不是最好的问题。 但是,为了完整性,这里是答案:
你会在bits/types.h
中找到定义(顶部的评论说,从不直接包含这个文件),但它在一堆宏中有点模糊。尝试解开它们的另一种方法是查看预处理器输出:
#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()
运算符。
编辑:刚看到关于__
的问题部分。 This answer has a good discussion。关键点是以__
开头的名称是为实现保留的(因此您不应该使用__
开始自己的定义。)
答案 1 :(得分:31)
正如“GNU C Library Reference Manual”所说
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.
因此,如果您想要在客户端和服务器之间表示文件大小的可靠方法,您可以:
off64_t
类型和stat64()
函数(因为它填充结构stat64
,其中包含off64_t
类型本身)。在32位和64位计算机上键入off64_t
保证大小相同。-D_FILE_OFFSET_BITS == 64
编译您的代码并使用常规off_t
和stat()
。将off_t
转换为固定大小的int64_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)都支持此功能。
答案 2 :(得分:6)
如果您在跟踪定义时遇到问题,可以使用编译器的预处理输出,它将告诉您需要知道的所有内容。 E.g。
$ 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;
答案 3 :(得分:4)
如果您正在编写便携式代码,答案是&#34;您无法告诉&#34;,好消息是您不需要。您的协议应该包括将大小写为(例如)&#34; 8个八位字节,大端格式&#34; (理想情况下检查实际大小是否适合8个八位字节。)