web-dev-qa-db-ja.com

off_t型の完全な定義はどこにありますか?

TCPを使用してクライアントからサーバーにファイルを送信しています。ファイルの終わりをマークするには、実際のデータの前にファイルサイズを送信します。そこで、statシステムコールを使用して、ファイルのサイズを見つけます。これはoff_tタイプです。サーバー側で適切に読み取ることができるように、それが何バイトを占有しているかを知りたいです。 <sys/types.h>で定義されています。しかし、私はその定義を理解していません。 __off_t or _off64_toff_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 
59
FourOfAKind

この答えはまだ投票されているので、ヘッダーファイルを調べる必要はほとんどないはずです。信頼性の高いコードを作成する場合は、標準を確認することで対応できます。 「私のマシンで_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;
}
_

その後:

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

ただし、何かのサイズを知りたい場合は、いつでもsizeof()演算子を使用できます。

編集:____に関する質問の一部を見ました。 この回答には良い議論があります 。重要な点は、____で始まる名前は実装用に予約されていることです(したがって、独自の定義を____で開始しないでください)。

71
Timothy Jones

「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_t_とstat()を使用します。
  3. _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を含む)はこの機能をサポートしています。

33
likern

定義のトレースに問題がある場合は、コンパイラの前処理された出力を使用して、知っておく必要のあるすべての情報を確認できます。例えば。

$ 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;
6
chutz

移植可能なコードを書いている場合、答えは「わかりません」です。良いニュースは、あなたがする必要がないということです。プロトコルには、サイズを(たとえば)「8オクテット、ビッグエンディアン形式」として書き込む必要があります(理想的には、実際のサイズが8オクテットに収まることを確認します)。

4
Martin Bonner