Saltar al contenido

¿Dónde encontrar la definición completa de tipo off_t?

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 y off_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:

  1. Usar off64_t tipo y stat64() funcionar en consecuencia (ya que llena la estructura stat64, que contiene off64_t tipo en sí). Escribe off64_t garantiza el mismo tamaño en máquinas de 32 y 64 bits.
  2. Como se mencionó antes, compile tu codigo con -D_FILE_OFFSET_BITS == 64 y uso habitual off_t y stat().
  3. Convertir off_t digitar int64_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;

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *