72 votes

Comment fread vraiment travailler?

La déclaration d' fread est le suivant:

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

La question est: Est-il une différence dans le rendement en lecture de deux de ces appels à l' fread:

char a[1000];
  1. fread(a, 1, 1000, stdin);
  2. fread(a, 1000, 1, stdin);

Il va lire 1000 octets à la fois à chaque fois?

103voto

Keith Thompson Points 85120

Il peut ou peut ne pas être une différence dans les performances. Il y a une différence sémantique.

fread(a, 1, 1000, stdin);

essaie de lire 1000 éléments de données, chacun de qui est de 1 octet de long.

fread(a, 1000, 1, stdin);

essaie de lire 1 de l'élément de données qui est de 1000 octets.

Ils sont différents parce qu' fread() renvoie le nombre d'éléments de données qu'il a pu lire, pas le nombre d'octets. Si il arrive à la fin de fichier (ou une condition d'erreur) avant de lire l'intégralité de 1000 octets, dont la première version a pour indiquer exactement le nombre d'octets à lire; le deuxième, juste échoue et renvoie 0.

Dans la pratique, il est probablement juste va appeler un niveau inférieur de la fonction qui tente de lire 1000 octets et indique combien d'octets réellement lus. Pour les plus grands lit, il peut faire plusieurs niveau inférieur appels. Le calcul de la valeur renvoyée par fread() est différent, mais la charge de calcul est trivial.

Il peut y avoir une différence si la mise en œuvre peut dire, avant de tenter de lire les données, qu'il n'y a pas suffisamment de données à lire. Par exemple, si vous lisez un de 900 octets du fichier, la première version de lire tous les 900 octets et retour 900, tandis que le second pourrait pas pris la peine de lire quoi que ce soit. Dans les deux cas, le fichier indicateur de position est avancé par le nombre de caractères lus, c'est à dire, 900.

Mais en général, vous devriez probablement choisir comment appeler sur la base de quelles informations vous avez besoin. Lire un seul élément de données si une lecture partielle n'est pas mieux que de ne pas le lire du tout. Lire en petits morceaux si partielle de lit sont utiles.

17voto

ArjunShankar Points 8476

Selon les spécifications, les deux peuvent être traités différemment par la mise en œuvre.

Si votre fichier est de moins de 1000 octets, fread(a, 1, 1000, stdin) (lire les éléments de 1000 de 1 octet chacun) seront toujours copier tous les octets jusqu'à ce que les expressions du FOLKLORE. D'autre part, le résultat d' fread(a, 1000, 1, stdin) (lire 1 1000 octets élément) stockés dans a est indéterminé, car il n'y a pas assez de données pour terminer la lecture de la première (et la seule) 1000 octets élément.

Bien sûr, certaines implémentations peuvent toujours copier le "partielle" de l'élément en tant que nombre d'octets nécessaires.

14voto

KennyTM Points 232647

Qui serait mise en œuvre en détail. Dans la glibc, les deux sont identiques en terme de performance, il est mis en œuvre essentiellement (Réf http://sourceware.org/git/?p=glibc.git;a=blob;f=libio/iofread.c):

size_t fread (void* buf, size_t size, size_t count, FILE* f)
{
    size_t bytes_requested = size * count;
    size_t bytes_read = read(f->fd, buf, bytes_requested);
    return bytes_read / size;
}

Notez que le C et POSIX standard ne garantit pas un objet de la taille de l' size besoin de lire à chaque fois. Si un objet ne peut pas être lu (par exemple, stdin seulement a 999 octets, mais vous avez demandés size == 1000), le fichier sera laissé dans un interdeterminate état (C99 §7.19.8.1/2).

Edit: Voir les autres réponses à propos de POSIX.

3voto

Artefacto Points 50896

Il peut y avoir aucune différence de performances, mais ces appels ne sont pas les mêmes.

  • fread renvoie le nombre d'éléments de la lecture, de sorte que ces appels seront de retour des valeurs différentes.
  • Si un élément ne peut pas être entièrement lu, sa valeur est indéterminée:

Si une erreur se produit, la valeur résultante de la fiche indicateur de position pour le stream est durée indéterminée. Si partielle d'un élément est lu, sa valeur est indéterminée. (ISO/IEC 9899:TC2 7.19.8.1)

Il n'y a pas beaucoup de différence dans la glibc mise en œuvre, qui multiplie la taille de l'élément par le nombre d'éléments pour déterminer le nombre d'octets à lire et divise le montant de lecture par le membre de la taille à la fin. Mais la version de la spécification d'un élément de taille 1 sera toujours vous dire le nombre exact d'octets à lire. Toutefois, si vous ne se soucient lire complètement les éléments d'une certaine taille, à l'aide de l'autre formulaire vous permet d'économiser de faire une division.

1voto

Mr.32 Points 6553

Encore une phrase de forme http://pubs.opengroup.org/onlinepubs/000095399/functions/fread.html est remarquable

Le fread() la fonction est de lire dans le tableau pointé par ptr jusqu'à nitems éléments dont la taille est spécifiée par la taille en octets, à partir du flux pointé par stream. Pour chaque objet, de la taille d'appels doit être faite à la fgetc() la fonction et les résultats stockés, dans l'ordre de lecture, dans un tableau de unsigned char exactement la superposition de l'objet.

Inshort dans les deux cas, les données seront accessibles par fgetc()...!

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X