Utilizzo della differenza di puntatori con printf ("%. * S")

Sep 12 2020

Il problema che sto affrontando ha a che fare con il intptr_ttipo di dati e il modo in cui fprintf()accetta argomenti per il %.*sformato. Il %.*sformato prevede che la precisione del campo abbia il tipo int, e forse non è irragionevole di per sé.

Non in questo caso però:

#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);
            }
        }
    }
}
  • Se lo compilo, non funziona bene %.*se il compilatore lo fa notare:

    avvertenza: la precisione del campo dovrebbe avere il tipo "int", ma l'argomento ha il tipo "intptr_t" (noto anche come "long") [-Wformat]

  • Se lo faccio int o;, funziona bene %.*sma ovviamente non è l'ideale, e il compilatore lo dice:

    avviso: la conversione implicita perde la precisione del numero intero: da "long" a "int" [-Wshorten-64-to-32]

Ora, questo è il codice demo e la dimensione massima che opuò contenere è 500qui, tuttavia, nel mio codice effettivo, può essere 10,000o anche 100,000(ancora molto entro la dimensione di un int a 32 bit, non è vero?)

Quindi cosa risolverà questo meglio con il minimo cambiamento?

Compilato su Clang (potrebbe essere molto simile su GCC) con -Wall -Wextra -pedantic.

Risposte

2 chux-ReinstateMonica Sep 12 2020 at 12:02

La differenza di due puntatori è il tipo ptrdiff_t. "... è il tipo intero con segno del risultato della sottrazione di due puntatori;"

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

Dato che entrambi puntano char in[501], la differenza rientra anche in un file int.
Lancia semplicemente. Si .*aspetta una corrispondenza int, non un intptr_tné ptrdiff_t.

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

O tutto in una volta:

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

p-inè più un ptrdiff_to un size_t. Ad ogni modo, in questo caso, userei 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);
}

Quindi aggiungi i controlli di errore.