El paso a paso o código que verás en este artículo es la resolución más sencilla y efectiva que encontramos a esta duda o dilema.
Solución:
Dado que esta respuesta aún se vota a favor, quiero señalar que casi nunca debería tener que buscar en los archivos de encabezado. Si desea escribir código confiable, es mucho mejor que busque en el estándar. Una pregunta mejor que “cómo es off_t
definido en mi máquina “es” cómo es off_t
definido por el estándar? “. Seguir el estándar significa que su código funcionará hoy y mañana, en cualquier máquina.
En este caso, off_t
no está definido por el estándar C. Es parte del estándar POSIX, que puede navegar aquí.
Desafortunadamente, off_t
no está definido de manera muy rigurosa. Todo lo que pude encontrar para definirlo está en la página de sys/types.h
:
blkcnt_t
yoff_t
serán tipos enteros con signo.
Esto significa que no puede estar seguro de su tamaño. Si está usando GNU C, puede usar las instrucciones en la respuesta a continuación para asegurarse de que sea de 64 bits. O mejor, puede convertirlo a un tamaño estándar definido antes de colocarlo en el cable. Así es como funcionan proyectos como los búferes de protocolo de Google (aunque es un proyecto de C ++).
Entonces, creo que “dónde encuentro la definición en mis archivos de encabezado” no es la mejor pregunta. Pero, para completar, aquí está la respuesta:
En mi máquina (y en la mayoría de las máquinas que usan glibc) encontrará la definición en bits/types.h
(como dice un comentario en la parte superior, nunca incluya directamente este archivo), pero está un poco oculto en un montón de macros. Una alternativa para tratar de desentrañarlos es mirar la salida del preprocesador:
#include
#include
int main(void)
off_t blah;
return 0;
Y luego:
$ gcc -E sizes.c | grep __off_t
typedef long int __off_t;
....
Sin embargo, si desea saber el tamaño de algo, siempre puede usar el sizeof()
operador.
Editar: Acabo de ver la parte de su pregunta sobre el __
. Esta respuesta tiene una buena discusión. los key el punto es que los nombres que comienzan con __
están reservados para la implementación (por lo que no debe comenzar sus propias definiciones con __
).
Como dice el “Manual de referencia de la biblioteca 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.
y
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.
Por lo tanto, si desea una forma confiable de representar el tamaño del archivo entre el cliente y el servidor, puede:
- Usar
off64_t
tipo ystat64()
funcionar en consecuencia (ya que llena la estructurastat64
, que contieneoff64_t
tipo en sí). Escribeoff64_t
garantiza el mismo tamaño en máquinas de 32 y 64 bits. - Como se mencionó antes, compile tu codigo con
-D_FILE_OFFSET_BITS == 64
y uso habitualoff_t
ystat()
. - Convertir
off_t
digitarint64_t
con tamaño fijo (estándar C99).
Nota: (mi libro ‘C en pocas palabras’ dice que es estándar C99, pero opcional en implementación). El estándar C11 más nuevo dice:
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.
Y sobre la implementación:
7.20 Integer types
... 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.
Por lo tanto, en general, el estándar C no puede garantizar tipos con tamaños fijos. Pero la mayoría de los compiladores (incluido gcc) admiten esta función.
Si tiene problemas para rastrear las definiciones, puede usar la salida preprocesada del compilador que le dirá todo lo que necesita saber. P.ej
$ cat test.c
#include
$ 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) ;
Si observa la salida completa, incluso puede ver la ubicación exacta del archivo de encabezado y el número de línea donde se definió:
# 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;