Las funciones ctime en C devuelven la misma cadena para diferentes valores de atime, mtime y ctime?

Nov 28 2020

Cuando se utiliza la stat()función en Mingw-W64, y la estructura se vuelve, aquí info, ¿por qué ctimevolver las mismas cadenas exactas para info.st_atime, mtimey ctime, a pesar de que los sus valores enteros son diferentes?

Si localtimese utiliza para obtener cada componente de tiempo por separado, los resultados difieren y parecen precisos; es decir, coinciden con las fechas de las carpetas de archivos que he observado.

ctime(&info.st_atime )  versus   localtime(&info.st_atime )->tm_wday,
                                 localtime(&info.st_atime )->tm_mon,
                                 localtime(&info.st_atime )->tm_mday,
                                 localtime(&info.st_atime )->tm_hour,
                                 localtime(&info.st_atime )->tm_min,
                                 localtime(&info.st_atime )->tm_sec,
                                 localtime(&info.st_atime )->tm_year

Hace más de tres años se hizo una pregunta similar sin respuesta.

¿Alguien sabe por qué y si hay o no documentación sobre las fechas en minGW-W64?

Gracias.


Aquí está el ejemplo de código completo. Es un conjunto de impresión feo.

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <fcntl.h>
#include <time.h>
#include <errno.h>

int main (void)

{
  DIR *dp;
  struct dirent *ep;
  struct stat info;
  int rc;
  char fl_name[300];

  dp = opendir("./SQLite3");

  if ( dp != NULL )
    {
      while ( ep = readdir( dp ) )
        {
          printf( "Name : %s, ", ep->d_name );
          if ( *( ep->d_name ) == '.' )
            { 
              printf(" non-useful file\n");
              continue;
            }

          sprintf( fl_name, "%s%s", "./SQLite3/", ep->d_name );

          if ( ( rc = stat( fl_name, &info ) ) != 0 )
             {
               printf( "rc : %d\n", rc );
               printf( "errno : %d, strerror : %s\n", errno, strerror( errno ) );
               break;
             }

          printf( "mode : %d, size : %d,\nst_atime : %slocal : %d %d %d %d : %d : %d %d,\ninteger value : %d\n"           
                                        "st_mtime : %slocal : %d %d %d %d : %d : %d %d,\ninteger value : %d\n"          
                                        "st_ctime : %slocal : %d %d %d %d : %d : %d %d,\ninteger value : %d\n\n",

                  info.st_mode, info.st_size, 
                  ctime(&info.st_atime ),
                  localtime(&info.st_atime )->tm_wday,
                  localtime(&info.st_atime )->tm_mon,
                  localtime(&info.st_atime )->tm_mday,
                  localtime(&info.st_atime )->tm_hour,
                  localtime(&info.st_atime )->tm_min,
                  localtime(&info.st_atime )->tm_sec,
                  localtime(&info.st_atime )->tm_year,
                  info.st_atime,

                  ctime(&info.st_mtime ),
                  localtime(&info.st_mtime )->tm_wday,
                  localtime(&info.st_mtime )->tm_mon,
                  localtime(&info.st_mtime )->tm_mday,
                  localtime(&info.st_mtime )->tm_hour,
                  localtime(&info.st_mtime )->tm_min,
                  localtime(&info.st_mtime )->tm_sec,
                  localtime(&info.st_mtime )->tm_year,
                  info.st_mtime,

                  ctime(&info.st_ctime ),
                  localtime(&info.st_ctime )->tm_wday,
                  localtime(&info.st_ctime )->tm_mon,
                  localtime(&info.st_ctime )->tm_mday,
                  localtime(&info.st_ctime )->tm_hour,
                  localtime(&info.st_ctime )->tm_min,
                  localtime(&info.st_ctime )->tm_sec,
                  localtime(&info.st_ctime )->tm_year ),
                  info.st_ctime;    
        }    
      printf( "Now : %ld\n", time(NULL) );
      printf( "Broke" );
      (void) closedir (dp);
    }
  else
    perror ("Couldn't open the directory");    
  return 0;
}

Los resultados de un archivo tienen el siguiente aspecto.

Name : testing.c, mode : 33206, size : 21092,
st_atime : Thu Nov 26 23:56:20 2020
local : 4 10 26 23 : 56 : 20 120,
integer value : 1606452980
st_mtime : Thu Nov 26 23:56:20 2020
local : 5 10 27 0 : 16 : 58 120,
integer value : 1606454218
st_ctime : Thu Nov 26 23:56:20 2020
local : 6 9 31 23 : 8 : 28 120,
integer value : 5767254

Tenga en cuenta que las cadenas de datos de ctime()son idénticas, aunque los valores enteros difieren para los tres. Además, el valor entero de ctimees un formato diferente al de atimey mtime. Los atimey mtimeparecen ser segundos desde el 1 de enero de 1970, pero no sé qué ctimees como 5767254.

Gracias.


Código fijo según comentario de @KamilCuk. Mi estupidez y mi fea impresión fueron la causa. Cambios a continuación y nuevos resultados.

  struct tm *local_tm_ptr;

    
          local_tm_ptr = localtime(&info.st_atime );
          printf( "mode : %d, size : %d,\nst_atime : %slocal : %d %d %d %d : %d : %d %d,\ninteger value : %ld\n",           
                  info.st_mode, info.st_size, 
                  ctime(&info.st_atime ),
                  local_tm_ptr->tm_wday,
                  local_tm_ptr->tm_mon,
                  local_tm_ptr->tm_mday,
                  local_tm_ptr->tm_hour,
                  local_tm_ptr->tm_min,
                  local_tm_ptr->tm_sec,
                  local_tm_ptr->tm_year,
                  info.st_atime );


          local_tm_ptr = localtime(&info.st_mtime );
          printf( "st_mtime : %slocal : %d %d %d %d : %d : %d %d,\ninteger value : %ld\n",
                  ctime(&info.st_mtime ),
                  local_tm_ptr->tm_wday,
                  local_tm_ptr->tm_mon,
                  local_tm_ptr->tm_mday,
                  local_tm_ptr->tm_hour,
                  local_tm_ptr->tm_min,
                  local_tm_ptr->tm_sec,
                  local_tm_ptr->tm_year,
                  info.st_mtime );


          local_tm_ptr = localtime(&info.st_ctime );
          printf( "st_ctime : %slocal : %d %d %d %d : %d : %d %d,\ninteger value : %ld\n\n",
                  ctime(&info.st_ctime ),
                  local_tm_ptr->tm_wday,
                  local_tm_ptr->tm_mon,
                  local_tm_ptr->tm_mday,
                  local_tm_ptr->tm_hour,
                  local_tm_ptr->tm_min,
                  local_tm_ptr->tm_sec,
                  local_tm_ptr->tm_year,
                  info.st_ctime );

Nuevos resultados.

Name : testing.c, mode : 33206, size : 21092,
st_atime : Thu Nov 26 23:56:20 2020
local : 4 10 26 23 : 56 : 20 120,
integer value : 1606452980
st_mtime : Fri Nov 27 00:16:58 2020
local : 5 10 27 0 : 16 : 58 120,
integer value : 1606454218
st_ctime : Sat Oct 31 23:08:28 2020
local : 6 9 31 23 : 8 : 28 120,
integer value : 1604200108

Respuestas

2 KamilCuk Nov 29 2020 at 03:10

Básicamente estás haciendo:

static char buffer[20]; // static buffer internal for asctime
char *my_asctime(int a) { // asctime
    snprintf(buffer, 20, "%d", a); // asctime converts the input to some output
    return buffer; // and returns pointer to internal buffer
}
int main() {
    printf("%s %s %s %s\n", 
       my_asctime(1),
       my_asctime(2),
       my_asctime(3),
       my_asctime(4)
   );
    // **Any** of the outputs are valid:
    // 1 1 1 1
    // 2 2 2 2
    // 3 3 3 3
    // 4 4 4 4
}

Todas asctime(implementaciones sensatas) escriben en la misma memoria y devuelven el mismo puntero . Entonces, cuando printfse ejecuta, solo imprime el contenido de la misma memoria. Tenga en cuenta que el orden de evaluación de los argumentos de las funciones no está secuenciado entre sí, pero el orden de evaluación de las llamadas a funciones tiene una secuencia indeterminada. Cualquiera de los posibles resultados de asctimeserá válido. Use asctime_ro llame uno tras otro en printfs separados .