Fou*_*ind 63 c sockets networking types header-files
我正在使用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
Run Code Online (Sandbox Code Playgroud)
Tim*_*nes 77
由于这个答案仍然被投票,我想指出你几乎不需要查看头文件.如果您想编写可靠的代码,那么通过查看标准可以获得更好的服务.比" off_t我的机器上如何定义"更好的问题是" off_t标准如何定义?".遵循标准意味着您的代码将在今天和明天在任何机器上运行.
在这种情况下,off_t不是由C标准定义的.它是POSIX标准的一部分,您可以在这里浏览.
不幸的是,off_t没有非常严格的定义.我能找到的所有内容都在页面上sys/types.h:
blkcnt_t并且off_t应该是有符号整数类型.
这意味着你无法确定它有多大.如果您使用的是GNU C,则可以使用下面的答案中的说明来确保它是64位.或者更好的是,您可以在将其放入线路之前转换为标准定义的大小.这就是Google的Protocol Buffers等项目的工作方式(尽管这是一个C++项目).
所以,我认为"我在哪里可以找到头文件中的定义"并不是最好的问题.但是,为了完整性,这里是答案:
你会发现定义bits/types.h(如顶部的注释所示,从不直接包含这个文件),但它在一堆宏中有点模糊.尝试解开它们的另一种方法是查看预处理器输出:
#include <stdio.h>
#include <sys/types.h>
int main(void) {
off_t blah;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
然后:
$ gcc -E sizes.c | grep __off_t
typedef long int __off_t;
....
Run Code Online (Sandbox Code Playgroud)
但是,如果您想知道某些内容的大小,您可以随时使用该sizeof()运算符.
编辑:刚刚看到你的问题的一部分__.这个答案有很好的讨论.关键点是以开头的名称__为实现保留(所以你不应该开始自己的定义__).
lik*_*ern 36
正如"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.
Run Code Online (Sandbox Code Playgroud)
和
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.
Run Code Online (Sandbox Code Playgroud)
因此,如果您想要在客户端和服务器之间表示文件大小的可靠方法,您可以:
off64_t类型和stat64()函数(因为它填充结构stat64,其中包含off64_t类型本身).off64_t在32位和64位计算机上键入相同大小的保证.-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.
Run Code Online (Sandbox Code Playgroud)
关于实施:
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.
Run Code Online (Sandbox Code Playgroud)因此,通常,C标准不能保证具有固定大小的类型.但大多数编译器(包括gcc)都支持此功能.
如果您在跟踪定义时遇到问题,可以使用编译器的预处理输出,它将告诉您需要知道的所有内容.例如
$ 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) ;
Run Code Online (Sandbox Code Playgroud)
如果查看完整输出,您甚至可以看到确切的头文件位置和定义它的行号:
# 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;
Run Code Online (Sandbox Code Playgroud)
...
# 91 "/usr/include/stdio.h" 3 4
typedef __off_t off_t;
Run Code Online (Sandbox Code Playgroud)