IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Bibliothèque standard C Discussion :

Questions générales sur fopen()


Sujet :

Bibliothèque standard C

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2007
    Messages
    69
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 69
    Points : 34
    Points
    34
    Par défaut Questions générales sur fopen()
    Salut a tous

    Ca fait un petit moment que je suis pas passé poser de questions sur le forum, alors j'en profite pour vous souhaiter a tous la bonne année, que du bon code et le moins possible de bug


    Je suis en train d'ecrire des librairies de fonctions pour piloter une carte flash depuis un microcontroleur, j'aimerais faire ma librairie "FILE" la plus proche possible des fontions d'entrées/sorties sur fichier (fopen, fclose, fseek, fwrite et fread) afin que les futurs codeurs connaissant ces fonctions de bases puissent les réutiliser tres simplement avec ma lib.

    Pour fseek, fwrite et fread, c'est ok ca marche bien

    Par contre au niveau de fopen, je me pose la question suivante, fopen renvoit un pointeur sur un objet fichier, hors cet objet fichier n'est déclaré à nul part.

    Comment procede l'OS pour renvoyer un pointeur sur l'objet file?
    L'objet est il créé automatiquement de maniere transparante au lancement du soft? (exemple un tableau de X objets FILE implémenté en mémoire)
    Alloue t il a chaque tentative d'ouverture de fichier l'espace necessaire de mémoire pour cet objet FILE? (cette solution me paraitrait assez improbable, car il faudrait qu'un espace alloué a l'interieur d'une fonction soit encore dispo lorsque celle ci se ferme)
    A combien de fichier ouverts simultanéments sommes nous limités? (si il existe une limitation autre que l'espace mémoire de la machine sur laquelle on travaille)


    Merci d'avance

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Ce n'est pas "L'objet fichier", mais "Une structure de type FILE".
    Et pour l'allocation, ça dépend de l'implémentation. Typiquement, il me semble que les objets FILE sont alloués dynamiquement par fopen(). (je n'en dirais pas autant des descripteurs de fichier retournés par open(), par contre).

    cette solution me paraitrait assez improbable, car il faudrait qu'un espace alloué a l'interieur d'une fonction soit encore dispo lorsque celle ci se ferme
    Tu sais, c'est ce que fait toujours malloc(), hein...


    Quant aux limitations, ça doit dépendre du système.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    Les fonctions d'E/S de la librairie standard ont été faites pour permettre à un programme de s'interfacer de manière standard avec des modules de plus bas niveau (appelés également modules ou drivers ... selon la terminologie). La communication avec le périphérique (occulté par le driver ...) se fait avec un protocole dépendant de ce périphérique et qui n'a donc rien à voir avec la langage C. Un exemple très simple : sous DOS/Windows, la console (qui est le périphérique de sortie standard par défaut) est un périphérique nommé CON. Le protocole de communication avec ce périphérique est très simple : données envoyés, données écrites (DOS interprétaient également quelques séquences spéciaux ...). Analyse le programme suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #include <stdio.h>
     
    int main()
    {
        FILE * con = fopen("con", "w");
     
        if (con != NULL)
        {
            fprintf(con, "Hello, world.\n");
            fclose(con);
        }
     
        return 0;
    }
    Citation Envoyé par Marmoccelle
    A combien de fichier ouverts simultanéments sommes nous limités?
    FOPEN_MAX. Sa valeur est dépendante du système.

  4. #4
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    Je crois avoir mal compris ton problème. Tu veux réimplémenter l'objet FILE et les fonctions fopen, fwrite, fread, etc. c'est ça? Le livre Le langage C ANSI de B. Kernighan et D. Ritchie t'aidera beaucoup. Sous UNIX par exemple la structure FILE encapsule un descripteur de fichier.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    typedef struct _iobuf {
        ...
        int file_descriptor;
        ..
    }FILE;
    Alors fopen c'est tout simplement (exemple) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    FILE * fopen(const char * filename, const char * mode)
    {
        FILE * f = malloc(sizeof(FILE));
     
        if (f != NULL)
        {
            ...
            f->file_descriptor = open(filename, ...);
            ...
        }
     
        return f;
    }
    Et fclose :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    int fclose(FILE * f)
    {
        int close_stat;
        ...
        close_stat = close(f->file_descriptor);
        free(f);
        ...
        return ...
    }

  5. #5
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par Melem Voir le message
    Je crois avoir mal compris ton problème. Tu veux réimplémenter l'objet FILE et les fonctions fopen, fwrite, fread, etc. c'est ça? Le livre Le langage C ANSI de B. Kernighan et D. Ritchie t'aidera beaucoup. Sous UNIX par exemple la structure FILE encapsule un descripteur de fichier.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    typedef struct _iobuf {
        ...
        int file_descriptor;
        ..
    }FILE;
    Alors fopen c'est tout simplement (exemple) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    FILE * fopen(const char * filename, const char * mode)
    {
        FILE * f = malloc(sizeof(FILE));
     
        if (f != NULL)
        {
            ...
            f->file_descriptor = open(filename, ...);
            ...
        }
     
        return f;
    }
    Et fclose :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    int fclose(FILE * f)
    {
        int close_stat;
        ...
        close_stat = close(f->file_descriptor);
        free(f);
        ...
        return ...
    }
    J'imagine que si sa cible disposait des fonctions open() et close(), il n'aurait pas posé la question...
    Pas de Wi-Fi à la maison : CPL

  6. #6
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par Marmoccelle Voir le message
    Par contre au niveau de fopen, je me pose la question suivante, fopen renvoit un pointeur sur un objet fichier, hors cet objet fichier n'est déclaré à nul part.

    Comment procede l'OS pour renvoyer un pointeur sur l'objet file?
    L'objet est il créé automatiquement de maniere transparante au lancement du soft? (exemple un tableau de X objets FILE implémenté en mémoire)
    Alloue t il a chaque tentative d'ouverture de fichier l'espace necessaire de mémoire pour cet objet FILE? (cette solution me paraitrait assez improbable, car il faudrait qu'un espace alloué a l'interieur d'une fonction soit encore dispo lorsque celle ci se ferme)
    A combien de fichier ouverts simultanéments sommes nous limités? (si il existe une limitation autre que l'espace mémoire de la machine sur laquelle on travaille)
    Ce qu'il faut comprendre, c'est que FILE est une structure (qui peut être opaque) qui contient tout ce qu'il faut pour gérer le fichier. Il est fort probable que cette structure soit allouée par malloc() et libérée par free() lors de l'appel de fclose().

    Mais les détails internes dépendent complètement de l'implémentation physique des fichiers, à moins que tu ne disposes déjà d'un driver de type 'Unix' (ou POSIX.1) avec les fonctions open(), close() etc. qui se charge des accès bas-niveau. Dans ce cas, oui, l'exemple du chapitre 8 du K&R cité par melem peut aider.

    Mais je note que tu as déjà codé fread() et fwrite(). OK, c'est la base. On peut voir ?
    Pas de Wi-Fi à la maison : CPL

  7. #7
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    Citation Envoyé par Emmanuel
    J'imagine que si sa cible disposait des fonctions open() et close(), il n'aurait pas posé la question
    Je crois plutôt que ça dépend de ce qu'on veut vraiment faire ...
    Citation Envoyé par Marmocelle
    Je suis en train d'ecrire des librairies de fonctions pour piloter une carte flash depuis un microcontroleur, j'aimerais faire ma librairie "FILE" la plus proche possible des fontions d'entrées/sorties sur fichier (fopen, fclose, fseek, fwrite et fread) afin que les futurs codeurs connaissant ces fonctions de bases puissent les réutiliser tres simplement avec ma lib.

  8. #8
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2007
    Messages
    69
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 69
    Points : 34
    Points
    34
    Par défaut
    Merci a vous 3 pour vos réponses, désolé pour mon mutisme, pas eu le temps de me reconnecter plus tot. Je vais réprendre chacune de vos interrogations une à une.

    @medinoc: désolé pour les abus de langage, la programmation n'etant pas ma formation initiale, il m'arrive de melanger les termes

    @Melem: oui c'est tout a fait ca, je suis parti de rien du tout, puis j'ai ecris les fonctions bas niveaux pour piloter les cartes SD/MMC, puis je me suis attelé aux routines de gestion de la FAT, et maintenant j'ecris les routines de hauts niveaux permettant le travail sur fichier (FILE_open, FILE_close, FILE_seek, FILE_read, FILE_write)

    @manu: oui c'est bien ce que j'avais compris concernant la structure FILE (d'ailleurs la mienne contient: la taille du fichier ouvert, le n° du premier cluster occupé par ce fichier, le n° du cluster du dossier dans lequel se trouve le fichier, etc...) Donc ce que je cherchais a comprendre c'etait ou se trouvaient les "structures FILE" crées a chaque appel de fopen() et comment l'espace mémoire leur était alloué.


    Je colle ici le code de ma fonction FILE_read():

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
     
    /**
     *      Read block of data from an opened file
     *
     *      Reads an array of uiCount elements, from the file and stores
     *  them in the block of memory uchBuffer.
     *      The postion indicator of the file is advanced by the total amount of bytes read
     *
     *      If end of file is reached, no bytes would be read (return 0).
     *
     *
     *      Notes:  Work for FAT16 and FAT32
     *
     *      @param  uiCount         Number of elements [1;512]
     *      @param  *pFile          Pointer to a file object
     *
     *      @return ...                     The total number of elements successfully read
     *                                              If this number differs from the uiCount parameter, 
     *                                              either an error occured or the End Of File was reached.
     **/
    unsigned int FILE_Read(unsigned int uiCount, _FILE* pFile)
    {
    	unsigned long ulgSector, ulgSector2;
    	unsigned int i;
    	_SD_ERROR status;
     
    	if( pFile->CurrentByte == pFile->FileSize )
    		return 0;		// EOF reached, no more bytes to read
     
    	if( (pFile->CurrentByte + (unsigned long)uiCount) > pFile->FileSize )
    		uiCount = (unsigned int)(pFile->FileSize - pFile->CurrentByte);		// can't read more than "FileSize" bytes
     
    	ulgSector = FAT_ClusterToSector(pFile->CurrentCluster) + pFile->SectorOffset;
     
    	if( (pFile->ByteOffset + uiCount) > BLOCK_LENGTH)
    	{
    		// We need to cross a sector boundary
    		pFile->SectorOffset++;				// next sector
    		if(pFile->SectorOffset == uchFAT_SectorsPerCluster)
    		{
    			// end of cluster, need to get the following
    			pFile->CurrentCluster = FAT_GetNextCluster(pFile->CurrentCluster);	// Set the new current cluster
    			ulgSector2 = FAT_ClusterToSector(pFile->CurrentCluster);
    			pFile->SectorOffset = 0;											// first sector of the new cluster
    		}
    		else	// stay in same cluster, but get next sector
    			ulgSector2 = ulgSector+1;
     
    		if(pFile->ByteOffset == BLOCK_LENGTH)
    			status = SD_SingleBlockRead(ulgSector2,(unsigned char*)uchBuffer);
    		else
    			status = SD_MultipleBlockRead(ulgSector,ulgSector2,pFile->ByteOffset,uiCount,(unsigned char*)uchBuffer);
     
    		if(status!=SD_Valid)
    			return 0;
    		pFile->ByteOffset += uiCount;
    		pFile->ByteOffset -= BLOCK_LENGTH;
    	}
    	else
    	{
    		// Read a single sector
    		if(SD_SingleBlockRead(ulgSector,(unsigned char*)uchBuffer) != SD_Valid)
    			return 0;
     
    		for(i=0;i<uiCount;i++)
    			uchBuffer[i]=uchBuffer[pFile->ByteOffset + i];
     
    		pFile->ByteOffset += uiCount;
    	}
    	pFile->CurrentByte += (unsigned long)uiCount;
    		return uiCount;
    }

    Bon par contre, malloc et free n'existent pas dans les librairies qui sont a ma disposition.
    Donc pour suivre la meme logique il faudrait que je reserve un espace de la mémoire pour la déclaration de X structures FILE (du coup je serais limité en nombre de fichiers pouvant etre ouvert simultanément, non pas par la quantité réelle de mémoire restante a un instant t, mais par le nombre que j'aurais fixé avant la compilation), cet espace ne sera alors utilisé que pour les structures FILE, puis dans ma routine FILE_open, je devrais aller voir si cet espace est deja plein ou non (variable globale qui comptabilise le nombre de fichiers ouverts?), si il reste encore de la place je déclare ma nouvelle structure en ram, puis je retourne le pointeur en fin d'execution de routine.

    Est ce la meilleure solution? en voyez vous d'autres?

    Merci d'avance

    PS: je code sur µC PIC18Fxxxx avec MPLAB C18

  9. #9
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    Citation Envoyé par Marmoccelle
    Bon par contre, malloc et free n'existent pas dans les librairies qui sont a ma disposition.
    Donc pour suivre la meme logique il faudrait que je reserve un espace de la mémoire pour la déclaration de X structures FILE (du coup je serais limité en nombre de fichiers pouvant etre ouvert simultanément, non pas par la quantité réelle de mémoire restante a un instant t, mais par le nombre que j'aurais fixé avant la compilation), cet espace ne sera alors utilisé que pour les structures FILE, puis dans ma routine FILE_open, je devrais aller voir si cet espace est deja plein ou non (variable globale qui comptabilise le nombre de fichiers ouverts?), si il reste encore de la place je déclare ma nouvelle structure en ram, puis je retourne le pointeur en fin d'execution de routine.

    Est ce la meilleure solution? en voyez vous d'autres?

    Merci d'avance
    Oui c'est presque ça. Mais les globales c'est mal donc mets plutôt tout ce qui doit être global dans une structure, comme ça on n'a plus qu'une seule variable globale (la structure) qui contient toutes les infos qu'on a besoin.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    struct opened_files_s {
        FILE files[FOPEN_MAX];
        int nb_opened_files;
    };
     
    struct opened_files_s g_opened_files;

  10. #10
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2007
    Messages
    69
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 69
    Points : 34
    Points
    34
    Par défaut
    Ok ca marche, finalement je suis pas si bete que ca

    Merci pour ton aide. Je vais aussi appliquer la technique de reduction du nombre de variables globales pour celles de la librairie FAT, car il y en a un bon paquet aussi ce sera en effet plus clair/simple avec une seule et unique structure regroupant tout.

    Question subsidiaire:
    Comment trouvez vous le code de ma fonction FILE_Read ? clair? brouillon? n'hesitez pas à critiquer s'il y a des choses que je dois améliorer sur ma facon de coder.

    Merci

  11. #11
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par Marmoccelle Voir le message
    Question subsidiaire:
    Comment trouvez vous le code de ma fonction FILE_Read ? clair? brouillon? n'hesitez pas à critiquer s'il y a des choses que je dois améliorer sur ma facon de coder.

    Merci
    Si tu as la casquette d'implémenteur (écrire des fonctions systèmes, par exemple), tu as le droit et même le devoir d'utiliser _ devant tous les identificateurs publics[1], pour éviter les clashes avec le code de l'application (_ interdit devant).

    Sinon, tu n'as pas le droit d'utiliser _ pour commencer un identificateur

    Eviter les lignes de plus de 80 colonnes
    Eviter les commentaires // (C99)
    Une indentation de 2 ou 3 colonnes suffit.
    Attention à l'anglais. J'ai corrigé ton texte...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
     
    /**
     *  Read block of data from an opened file
     *
     * Reads an block of uiCount bytes, from the file and stores
     * in into the memory block named uchBuffer.
     * The postion indicator of the file is moved foward of the total
     * amount of bytes read
     *
     * If end of file is reached, no bytes would be read (returns 0).
     *
     *
     * Notes:  Works for FAT16 and FAT32
     *
     * @param  uiCount Maximum number of bytes to be read [1 to 512]
     * @param  *pFile  Pointer to a file object
     *
     * @return ... The total number of bytes successfully read
     *            If this number differs from the uiCount parameter,
     *            either an error occured or the End Of File was reached.
     **/
    unsigned int FILE_Read (unsigned int uiCount, _FILE * pFile)
    {
       unsigned long ulgSector, ulgSector2;
       unsigned int i;
       _SD_ERROR status;
     
       if (pFile->CurrentByte == pFile->FileSize)
       {                            /* EOF reached, no more bytes to read */
          return 0;
       }
       if ((pFile->CurrentByte + (unsigned long) uiCount) > pFile->FileSize)
       {
          /* can't read more than "FileSize" bytes */
          uiCount = (unsigned int) (pFile->FileSize - pFile->CurrentByte);
       }
     
       ulgSector =
          FAT_ClusterToSector (pFile->CurrentCluster) + pFile->SectorOffset;
     
       if ((pFile->ByteOffset + uiCount) > BLOCK_LENGTH)
       {
          /* We need to cross a sector boundary */
          pFile->SectorOffset++;    /* next sector */
          if (pFile->SectorOffset == uchFAT_SectorsPerCluster)
          {
             /* end of cluster, need to get the following */
     
             /* Set the new current cluster */
             pFile->CurrentCluster = FAT_GetNextCluster (pFile->CurrentCluster);
             ulgSector2 = FAT_ClusterToSector (pFile->CurrentCluster);
             pFile->SectorOffset = 0; /* first sector of the new cluster */
          }
          else
          {
             /* stay in same cluster, but get next sector */
             ulgSector2 = ulgSector + 1;
          }
          if (pFile->ByteOffset == BLOCK_LENGTH)
          {
             status =
                SD_SingleBlockRead (ulgSector2, (unsigned char *) uchBuffer);
          }
          else
          {
             status =
                SD_MultipleBlockRead (ulgSector, ulgSector2, pFile->ByteOffset,
                                      uiCount, (unsigned char *) uchBuffer);
          }
          if (status != SD_Valid)
          {
             return 0;
          }
     
          pFile->ByteOffset += uiCount;
          pFile->ByteOffset -= BLOCK_LENGTH;
       }
       else
       {
          /* Read a single sector */
          if (SD_SingleBlockRead (ulgSector, (unsigned char *) uchBuffer) !=
              SD_Valid)
          {
             return 0;
          }
     
          for (i = 0; i < uiCount; i++)
          {
             uchBuffer[i] = uchBuffer[pFile->ByteOffset + i];
          }
          pFile->ByteOffset += uiCount;
       }
       pFile->CurrentByte += (unsigned long) uiCount;
       return uiCount;
    }
    --------------
    [1] Sauf fonction publique standard ou dument définie comme File_read(), bien sûr.
    Pas de Wi-Fi à la maison : CPL

  12. #12
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    Je trouve le code bien fait, en tout cas c'est clair. Mais il y a trop de cast et la plupart du temps inutiles. En effet certaines conversions en C se font implicitement (automatiquement). En particulier dans ton cas, tous ces cast sont inutiles! (tous sans exception, si bien sûr uchBuffer est bel et bien un tableau de unsigned char comme son nom laisse supposer).

  13. #13
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2007
    Messages
    69
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 69
    Points : 34
    Points
    34
    Par défaut
    Ok merci a vous 2.

    @Manu: en fait je suis juste une casquette d'electronicien, habituellement plus à l'aise à manipuler de l'assembleur que du C, le coup du "_" devant les ID publics je ne connaissais pas du tout, tu as des liens qui pourraient éclaircir un peu tout ca?

    Pour les commentaires "//" c'est une sale habitude que j'ai prise, j'arrive pas à m'en défaire sinon ok pour les lignes de plus de 80 colonnes, je vais me mettre un repere pour pas dépasser.
    Pour l'indentation tu peux développer stp? est ce que ce sont les décalages (tabulations) au départ de chaque ligne?

    @Melem: merci, en fait j'ai rajouté tous ces casts car mon compilo me mettais pas mal de warning a la compilation, du coup j'ai pris l'habitude de quasi tout caster (surtout sur les calculs faisant intervenir des données de différents formats)

  14. #14
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Euh.. uchBuffer, c'est un cast de unsigned char * en unsigned char * ?

    Sinon, le cast d'un type entier en type entier plus petit, il indique bien qu'il y a risque de perte. Si tu es conscient de ce que tu fais, tu peux mettre le cast, mais tu devrais vérifier (en mode debug au moins) que tu n'a pas fait de dépassement de capacité...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  15. #15
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par Marmoccelle Voir le message
    en fait je suis juste une casquette d'electronicien,
    Pareil.
    habituellement plus à l'aise à manipuler de l'assembleur que du C, le coup du "_" devant les ID publics je ne connaissais pas du tout, tu as des liens qui pourraient éclaircir un peu tout ca?
    http://emmanuel-delahaye.developpez.com/codage.htm

    en fait j'ai rajouté tous ces casts car mon compilo me mettais pas mal de warning a la compilation, du coup j'ai pris l'habitude de quasi tout caster (surtout sur les calculs faisant intervenir des données de différents formats)
    Le problème, c'est que souvent, ça ne résout rien et que ça cache silencieusement les problèmes...

    Chaque warning doit susciter une reflexion sur le choix des types des variables. En principe, on s'en sort avec des tableaux de char, des int et des doubles. Dans de rares cas, on a besoin des long.

    Quand aux unsigned, ils sont utiles si on est certain que la valeur ne peut être négative. Attention aux boucles décroissantes !
    Pas de Wi-Fi à la maison : CPL

  16. #16
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2007
    Messages
    69
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 69
    Points : 34
    Points
    34
    Par défaut
    Alors concernant uchBuffer, je l'ai déclaré comme ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    unsigned char uchBuffer[512];
    Prototype d'une routine demandant un pointeur sur un buffer de unsigned char:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    _SD_ERROR SD_SingleBlockRead(unsigned long ulgBlockNumber, unsigned char* uchBuffer);
    Et a chaque fois que j'utilise un pointeur sur ce buffer, je me retrouve face au meme warning, d'ou les casts (unsigned char*):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Warning [2066] type qualifier mismatch in assignment
    SD_SingleBlockRead(ulgSector,uchBuffer)
    Il y a surement qq chose que j'ai mal fait, mais je n'arrive pas à trouver quoi

  17. #17
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Dans le cas présent, à part choisir ton compilateur, je ne vois pas trop ce que tu as pu mal faire.
    Et encore, c'est en supposant que tu avais le choix...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  18. #18
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2007
    Messages
    69
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 69
    Points : 34
    Points
    34
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Dans le cas présent, à part choisir ton compilateur, je ne vois pas trop ce que tu as pu mal faire.
    Et encore, c'est en supposant que tu avais le choix...
    Ok ca me rassure, en effet je n'ai pas le choix du compilo



    Citation Envoyé par Emmanuel Delahaye Voir le message
    Le problème, c'est que souvent, ça ne résout rien et que ça cache silencieusement les problèmes...
    Je vais essayer de virer les casts supperflus, mais le probleme c'est que j'ai des tonnes de calculs dans lesquels les uchar, uint et ulong sont ajoutés, soustrais, divisés, etc... (je ne peux pas me permettre de déclarer que des données du meme type ulong, car ce serait du gaspillage de mémoire et je n'ai pas la quantité suffisante pour ca)

    Citation Envoyé par Emmanuel Delahaye Voir le message
    Chaque warning doit susciter une reflexion sur le choix des types des variables. En principe, on s'en sort avec des tableaux de char, des int et des doubles. Dans de rares cas, on a besoin des long.

    Quand aux unsigned, ils sont utiles si on est certain que la valeur ne peut être négative. Attention aux boucles décroissantes !
    Pour ca pas de bleme, je n'ai quasi aucune boucle décroissante, dans les rares cas ou je dois en avoir une, je déclare une variable signed. L'ensemble de mes données ne peut etre négatives, d'ou les unsigned systématiques.

    Concernant la quantité de long utilisée, c'est fortement lié a l'application développée, les doubles ne me sont d'aucune utilité puisque les plus grandes données manipulées sont constituées de 4 octets (FAT32 inside), et ayant beaucoup d'opérations a réaliser sur ces données, le plus simple et le plus rapide pour moi etait d'utiliser directement le type long

  19. #19
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par Marmoccelle Voir le message
    Je vais essayer de virer les casts supperflus, mais le probleme c'est que j'ai des tonnes de calculs dans lesquels les uchar, uint et ulong sont ajoutés, soustrais, divisés, etc... (je ne peux pas me permettre de déclarer que des données du meme type ulong, car ce serait du gaspillage de mémoire et je n'ai pas la quantité suffisante pour ca)

    Pour ca pas de bleme, je n'ai quasi aucune boucle décroissante, dans les rares cas ou je dois en avoir une, je déclare une variable signed. L'ensemble de mes données ne peut etre négatives, d'ou les unsigned systématiques.
    Mais tu as parlé de soustraction, alors méfiance...
    Pas de Wi-Fi à la maison : CPL

  20. #20
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2007
    Messages
    69
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 69
    Points : 34
    Points
    34
    Par défaut
    Oui en effet, mais aucun probleme, pour chacune des opérations de soustractions je sais que le résultat ne peut etre que positif dans chacun des cas que l'on pourra rencontrer.

    Je marque sijet en "resolu", merci pour votre aide

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Question générales sur les IG en Java
    Par link182 dans le forum Interfaces Graphiques en Java
    Réponses: 3
    Dernier message: 18/02/2006, 11h42
  2. [LDAP] Questions générales sur LDAP
    Par guiguisi dans le forum Autres SGBD
    Réponses: 5
    Dernier message: 25/05/2005, 10h05
  3. questions générales sur Java Web Start
    Par Shiryu44 dans le forum JWS
    Réponses: 12
    Dernier message: 11/04/2005, 15h33
  4. question générale sur les conteneurs
    Par tut dans le forum C++
    Réponses: 6
    Dernier message: 01/09/2004, 10h11
  5. Question générale sur les affectations ?
    Par Clemaster dans le forum C++
    Réponses: 5
    Dernier message: 09/08/2004, 17h03

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo