Utilisation de la différence de pointeurs avec printf («%. * S»)

Sep 12 2020

Le problème auquel je suis confronté est lié au intptr_ttype de données et à la manière dont les fprintf()arguments du %.*sformat sont acceptés. Le %.*sformat s'attend à ce que la précision du champ soit de type int, et ce n'est peut-être pas déraisonnable en soi.

Pas dans ce cas cependant:

#include <stdio.h>
#include <stdint.h>
int main() {
    char fname[] = "Some_File.txt";
    FILE *write = fopen(fname,"w");
    
    if(write!=NULL){

        printf("\n\tType below :\n\n");
        char in[501]=""; char *p;

        while(1){
            fgets(in,MAX_LN,stdin);

    /*** Region with compiler warnings begins ***/
            if((p=strstr(in,"/end/"))!=0){
                intptr_t o = p-in;
                fprintf(write,"%.*s",o,in);
    /*** Region with compiler warnings ends ***/
                fclose(write);
                break;
            }
            else{
                fputs(in,write);
            }
        }
    }
}
  • Si je compile ceci, cela ne fonctionne pas bien avec %.*s, et le compilateur le souligne:

    avertissement: la précision du champ doit avoir le type 'int', mais l'argument a le type 'intptr_t' (aka 'long') [-Wformat]

  • Si je le fais int o;, il joue bien avec %.*smais bien sûr n'est pas idéal, et le compilateur le dit:

    avertissement: la conversion implicite perd la précision entière: 'long' en 'int' [-Wshorten-64-to-32]

Maintenant, c'est du code de démonstration, et la taille maximale qui opeut contenir est 500ici, cependant, dans mon code réel, cela peut être 10,000ou même 100,000(toujours très dans la taille d'un int 32 bits, n'est-ce pas?)

Alors, qu'est-ce qui résoudra le mieux cela avec le moins de changements?

Compilé sur Clang (peut être très similaire sur GCC) avec -Wall -Wextra -pedantic.

Réponses

2 chux-ReinstateMonica Sep 12 2020 at 12:02

La différence de deux pointeurs est le type ptrdiff_t. "... est le type entier signé du résultat de la soustraction de deux pointeurs;"

// intptr_t o = p-in;
ptrdiff_t o = p - in;

Compte tenu de ces deux points char in[501], la différence s'inscrit également dans un int.
Jetez simplement. L' .*attend un match int, pas un intptr_tni ptrdiff_t.

// fprintf(write,"%.*s",o,in);
fprintf(write,"%.*s", (int) o, in);

Ou tout à la fois:

fprintf(write,"%.*s", (int) (p - in), in);
1 Ry- Sep 12 2020 at 11:44

p-inest plus un ptrdiff_tou un size_t. Quoi qu'il en soit, dans ce cas, j'utiliserais fwrite:

if ((p = strstr(in, "/end/")) != NULL) {
    size_t len = p - in;
    fwrite(in, sizeof(char), len, write);
    fclose(write);
    break;
} else {
    fputs(in, write);
}

Ajoutez ensuite des vérifications d'erreurs.