Verwenden der Zeigerdifferenz mit printf ("%. * S")

Sep 12 2020

Das Problem, mit dem ich konfrontiert bin, hat mit dem intptr_tDatentyp und der Art und Weise zu tun, wie fprintf()Argumente für das %.*sFormat verwendet werden. Das %.*sFormat erwartet int, dass die Feldgenauigkeit einen Typ hat , und vielleicht ist das an sich nicht unangemessen.

In diesem Fall jedoch nicht:

#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);
            }
        }
    }
}
  • Wenn ich das kompiliere, funktioniert es nicht gut damit %.*s, und der Compiler weist darauf hin:

    Warnung: Die Feldgenauigkeit sollte den Typ 'int' haben, aber das Argument hat den Typ 'intptr_t' (auch bekannt als 'long') [-Wformat]

  • Wenn ich es schaffe int o;, spielt es gut mit, ist %.*saber natürlich nicht ideal, und der Compiler sagt das auch:

    Warnung: Die implizite Konvertierung verliert an ganzzahliger Genauigkeit: 'long' bis 'int' [-Wshorten-64-to-32]

Nun, dies ist Demo-Code, und die maximale Größe, die enthalten sein okann, ist 500hier, aber in meinem tatsächlichen Code kann es sein 10,000oder sogar 100,000(immer noch sehr viel in der Größe eines 32-Bit-Int, nicht wahr?)

Was löst dieses Problem am besten mit den geringsten Änderungen?

Kompiliert auf Clang (könnte auf GCC sehr ähnlich sein) mit -Wall -Wextra -pedantic.

Antworten

2 chux-ReinstateMonica Sep 12 2020 at 12:02

Der Unterschied zwischen zwei Zeigern ist der Typ ptrdiff_t. "... ist der vorzeichenbehaftete Integer-Typ des Ergebnisses der Subtraktion von zwei Zeigern;"

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

Angesichts dieser beiden Punkte char in[501]passt der Unterschied auch in eine int.
Einfach besetzen. Das .*erwartet ein Match int, kein intptr_tNor ptrdiff_t.

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

Oder auf einmal:

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

p-inist eher ein ptrdiff_toder ein size_t. In diesem Fall würde ich jedenfalls Folgendes verwenden 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);
}

Fügen Sie dann Fehlerprüfungen hinzu.