ubuntuusers.de

Warnung: Vergleich ist durch beschränkten Wertebereich des Datentyps stets »wahr«

Status: Gelöst | Ubuntu-Version: Ubuntu 12.04 (Precise Pangolin)
Antworten |

Dakuan

Avatar von Dakuan

Anmeldungsdatum:
2. November 2004

Beiträge: 6489

Wohnort: Hamburg

Ich habe wohl wieder mal ein Brett vorm Kopf und benötige einen kleinen Denkanstoß.

Ich bekomme obige unschöne Warnung, und kann damit nicht wirklich etwas anfangen. Hier erstmal der zugehörige C-Code:

 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
/*
**      Minimal check of the filetype
**      returns 1 if file is ok, otherwise 0
*/
int check_file( FILE * fp )
{
    /*unsigned*/ char check_buf[16];
    int  n;
    
    n = fread( check_buf, 1, 16, fp );
    rewind( fp );
    if( n == 16 ) {
        if( check_buf[0] != 0xFF  ||  check_buf[1] != 0xD8 ) /* SOI, Start Of Image */
            return 0;
        if( check_buf[2] == 0xFF  &&  check_buf[3] == 0xE0 ) { /* APP0 JFIF */
            if( strncmp( check_buf + 6, "JFIF", 4 ) == 0 )
                return 1;
            else
                return 0;
        }
        if( check_buf[2] == 0xFF  &&  check_buf[3] == 0xE1 ) { /* APP1 Exif */
            if( strncmp( check_buf + 6, "Exif", 4 ) == 0 )
                return 1;
            else
                return 0;
        }
    }
    return 0;
}

Ich habe diese Funktion gerade in ein uraltes Projekt eingefügt, um einen nervigen Programmfehler zu beseitigen, der allerdings erst durch eine kürzliche Erweiterung auftritt (bisher keine Prüfung ob es wirklich eine JPG Datei ist).

Ich sollte vielleicht noch erwähnen, das der Code per "extern C" in einem C++ Programm mitverwendet wird.

Wenn ich den Puffer als "unsigned char" deklariere, geht zwar die Warnung weg, aber ich bekomme einen neuen Fehler in den Zeilen 17 und 23:

1
jcomtool.c:383: Fehler: ungültige Umwandlung von »unsigned char*« in »const char*«

Wie komme ich aus dieser Zwickmühle am elegantesten heraus?

Nachtrag: der Kern des Tools soll auch als eigenständiges Programm vorhanden sein, damit ich es auch in Scripten verwenden kann. Deshalb wollte ich das als C Programm bestehen lassen.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13185

Dakuan schrieb:

Ich habe wohl wieder mal ein Brett vorm Kopf und benötige einen kleinen Denkanstoß.

Ich bekomme obige unschöne Warnung, und kann damit nicht wirklich etwas anfangen. Hier erstmal der zugehörige C-Code:

Welche Zeile wird denn angemahnt?

Dakuan

(Themenstarter)
Avatar von Dakuan

Anmeldungsdatum:
2. November 2004

Beiträge: 6489

Wohnort: Hamburg

Ups, ich dachte das ist klar. Es sind die Zeilen 13, 15, und 21, also alle Zeilen wo direkt Hex Werte verglichen werden und das natürlich für jeden einzelnen Vergleich (also insgesamt 6 mal).

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13185

Dakuan schrieb:

Ich sollte vielleicht noch erwähnen, das der Code per "extern C" in einem C++ Programm mitverwendet wird.

Interessanterweise frißt mein gcc das problemlos:

$ gcc --version
gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ head x.c
#include <stdio.h>
#include <string.h>

/*
**      Minimal check of the filetype
**      returns 1 if file is ok, otherwise 0
*/
int check_file( FILE * fp )
{
    /*unsigned*/ char check_buf[16];
$ gcc -c -Wall -ansi x.c
$ 

Aber g++ hat auch nix zu meckern:

$ g++ --version
g++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ { echo 'extern "C" {'; cat x.c; echo '}' ;} >|xx.c
$ head xx.c 
extern "C" {
#include <stdio.h>
#include <string.h>

/*
**      Minimal check of the filetype
**      returns 1 if file is ok, otherwise 0
*/
int check_file( FILE * fp )
{
$ g++ -c -Wall -ansi xx.c
$ 

Dakuan schrieb:

Ups, ich dachte das ist klar. Es sind die Zeilen 13, 15, und 21, also alle Zeilen wo direkt Hex Werte verglichen werden und das natürlich für jeden einzelnen Vergleich (also insgesamt 6 mal).

Naja, 0xFF ist ja außerhalb von "signed char". Insofern erscheint es schon logisch, dort einen Fehler zu melden. Da Du sowieso Binärdaten in check_buf hältst, würde ich es "unsigned char" deklarieren.

Was uns zu dem zweiten Fehler bringt: in meiner Ansicht sind das Zeilen mit return. Das kann eigentlich nicht sein. Mindestens müssten dann 19 und 25 ebenfalls angemeckert werden.

Ich vermute daher, dass Du eher Zeile 15 und 21 meinst. Das ist nun auch wieder logisch, denn Du vergleichst Binärfolgen ("unsigned char") mit Zeichenketten ("signed char"). Du wirst wohl den Zeiger auf die Binärdaten casten müssen.

1
            if( strncmp( (const char*) check_buf + 6, "JFIF", 4 ) == 0 )

Damit verschwinden bei mir die Fehlermeldungen.

Ciao

robert

Dakuan

(Themenstarter)
Avatar von Dakuan

Anmeldungsdatum:
2. November 2004

Beiträge: 6489

Wohnort: Hamburg

Ich hatte etwas aus dem Funktionskopf herausgelöscht, ohne zu bedenken, dass ich dann auch die Zeilennummern im Text anpassen muss.

Du wirst wohl den Zeiger auf die Binärdaten casten müssen.

Ja, das ist wohl der einfachste Weg. Eleganter wäre natürlich Strukturen zu verwenden, aber da es sich um 2 verschiedene handelt, müsste man die dann auch wieder casten.

Aber so ganz ist mir noch nicht klar, woher der Compiler wissen will, das die Bedingung immer wahr ist. Ich werde das aber gleich mal mit anderen Werten testen (hab da so'n Verdacht).

Dakuan

(Themenstarter)
Avatar von Dakuan

Anmeldungsdatum:
2. November 2004

Beiträge: 6489

Wohnort: Hamburg

Das Brett beginnt sich zu lösen.

Ich denke es ist so: bei den Werten im Zeichenpuffer findet eine Vorzeichenerweiterung statt, bei den Hex Konstanten jedoch nicht. Daher sind alle Werte mit gesetztem Bit 7 immer ungleich mit denen im Puffer wenn mit Vorzeichen verglichen wird.

[Edit]: Ich habe mir jetzt mal angeschaut, wie die Profis das Problem gelöst haben. Da werden die Signaturen als Array abgelegt

static const unsigned char sig[] = { ... };

und dann mit memcmp() verglichen. Da wird dann auch kein Cast benötigt.

Antworten |