Question

Je dois écrire des données dans un fichier binaire en utilisant les fonctions E / S de C. Le code suivant provoque une exception d'exécution:


#include "stdio.h"

int main(int argc,char* argv[]) {
    FILE *fp = fopen("path_to_file.bin","wb");
    if(fp == NULL) {
        printf("error creating file");
        return -1;
    }
    int val = 4;
    fwrite((const void*)val,sizeof(int),1,fp);
    fclose(fp);
    return 0;
}

Le code meurt à l'fwrite. Pouvez-vous trouver ce que je fais mal? Apparemment, je suis, en essayant d'accéder aux données à 0x0000004 ou quelque chose comme ça.

Merci!

Était-ce utile?

La solution

 fwrite((const void*)val,sizeof(int),1,fp);

devrait être:

 fwrite((const void*) & val,sizeof(int),1,fp);

BTW, si vous n'utilisez pas le casting, vous obtiendrez un message d'erreur sensible. Casts ont tendance à être utilisés par C (et C ++) programmeurs beaucoup plus souvent qu'ils devraient être -. Une bonne règle de base est « si elle a besoin d'un casting, il est probablement faux »

Autres conseils

Je pense que la réponse de Neil peut être améliorée. Je me rends compte qu'il est déjà accepté, c'est donc juste pour montrer un peu de contraste (ce qui est la raison pour laquelle je ne suis pas simplement modifier son).

fwrite(&val, sizeof val, 1, fp);

Deux améliorations:

  • Pas de coulée pointeur, car il est pas nécessaire en C et peut cacher des erreurs.
  • Utilisez sizeof directement sur l'objet, puisque c'est ce que vous passez un pointeur vers. Fait beaucoup de sens pour moi, et il est plus sûr que vous répéter et en utilisant le nom du type.

Ajout à la réponse de Neil: cela fonctionne lorsque vous lisez et l'écriture du fichier sur la même plate-forme. Les choses peuvent devenir bizarre si vous lisez / écriture sur toutes les plateformes avec différentes boutisme.

#include "stdio.h"

int main(int argc,char* argv[]) {
    FILE *fp = fopen("path_to_file.bin","wb");
    if(fp == NULL) {
        printf("error creating file");
        return -1;
    }
    int val = 4;
    fwrite((const void*)val,sizeof(int),1,fp);

Vous devez fournir une adresse pas lui-même entière.

Additionnellement vous ne devriez pas utiliser l'entier de telle manière:

  1. Il peut différer endianess sur des ordinateurs différents (comme indiqué)
  2. Il peut varier en taille. Sur les ordinateurs vraiment vieux, il peut être 1 ou 2 octets. Le plus moderne, il sera 4 mais peut être 8 aussi bien (certains ordinateurs 64 bits). Sur certaines architectures étranges, il peut être même 36 bits. int32_t val = 4; fwrite((const void *)val, 4, 1, fp) devrait résoudre le problème.

Vous pouvez penser que votre logiciel ne sera jamais besoin d'être porté. Eh bien - de nombreux concepteurs (logiciels et matériels) ont émis des hypothèses similaires. Parfois, il est trop coûteux de ne pas les faire -. Mais dans ce cas, il est juste une question de quelques contrôles supplémentaires

    fclose(fp);
    return 0;
}

J'ai aussi fait face à ce genre de problème. Donc, voici ma solution.

fwrite(val, sizeof(val[0], sizeof(val)/sizeof(val[0]), fp);

  

Apparemment, je suis, en essayant d'accéder aux données à 0x0000004 ou quelque chose comme ça.

int val = 4

Il y a la question. fwrite est conçu pour fonctionner avec des cordes, et en tant que tel sa première entrée est un pointeur, l'emplacement d'une chaîne de caractères dans la mémoire. Vous passez directement la valeur de val (4) plutôt que l'adresse de val à fwrite; Cependant, la mémoire à 0x00000004 la mémoire est de programme valide et donc une erreur est donnée.

Pour corriger cela, changer ceci:

fwrite((const void*)val,sizeof(int),1,fp);

Dans ceci:

fwrite((const void*)&val, sizeof(int), 1, fp);

L'opérateur « & » indique l'emplacement de val. Ce serait une adresse valide dans la mémoire.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top