2012-04-09 4 views
0

Warum funktioniert der folgende Code? Sollte das ein Übersetzungsfehler (oder zumindest ein Laufzeitfehler) sein?Warum kann ich einem Zeiger eine Zeichenfolge zuweisen?

#include <stdio.h> 

int main(int argc, char** argv){ 
     float *buf = "happy holiday";  // notice the float 
     printf("content of buf = %s\n",buf); //its working 
     return 0; 
} 

ich es kompiliert und bekam nur eine Warnung:

~/Desktop/cTest>gcc -o run run.c 
run.c: In function `main': 
run.c:4: warning: initialization from incompatible pointer type 

Antwort

3

Sie immer mit -Wall -Werror -Wextra (mindestens) zusammenstellen sollte. Dann erhalten Sie folgende:

cc1: warnings being treated as errors 
test.c: In function 'main': 
test.c:4: warning: initialization from incompatible pointer type 
test.c:5: warning: format '%s' expects type 'char *', but argument 2 has type 'float *' 
test.c: At top level: 
test.c:3: warning: unused parameter 'argc' 
test.c:3: warning: unused parameter 'argv' 

Es „funktioniert“, weil in der Praxis gibt es keinen Unterschied gibt zwischen einem char * und einem float * unter der Haube auf Ihrer Plattform. Ihr Code ist wirklich nicht anders zu:

#include <stdio.h> 

int main(int argc, char** argv){ 
     float *buf = (float *)"happy holiday"; 
     printf("content of buf = %s\n",(char *)buf); 
     return 0; 
} 

Dies ist wohldefinierte Verhalten, es sei denn, die Ausrichtungsanforderungen von float und char unterscheiden, in welchem ​​Fall es in undefinierten Verhalten führt (siehe C99, 6.3.2.3 p7).

+3

Ich stimme Ihrer Behauptung nicht, dass mindestens diese Warnoptionen verwendet werden sollten. Selbst in diesem winzigen Beispiel haben Sie falsche Positive (die nicht verwendeten Parameterwarnungen) erzeugt, die * normalerweise * nicht unterdrückt werden können, ohne unnötigen Code hinzuzufügen. Hier könnte die andere Form von 'main' verwendet werden, aber was wäre, wenn Sie nur' argv' brauchen, aber nicht 'argc'? Ich bin ein großer Befürworter des Compilers warnen (und Fehler) auf ungültigen oder definitiv schlechten Code, aber die Reihe von Optionen, die Sie vorgeschlagen, wird notwendigerweise tadellos guten Code zurückweisen, es sei denn, Sie bemühen sich, es gcc's Willen zu verkomplizieren ... –

+0

@R .. Ich kann mit den trivialen Fixes leben, um mit den "falschen" positiven Ergebnissen im Austausch für den Schutz, den es bietet, umzugehen. Was befürworten Sie stattdessen? –

+0

Normalerweise verwende ich '-Wall' (aber nicht' -Wextra') und schalte dann einige Optionen mit '-Wno- *' aus (z. B. nicht verwendete Funktionsparameter). –

1

Dieses Programm ist nicht streng konform, ein Compiler muss eine Diagnose ausgeben und hat das Recht, die Kompilierung abzulehnen. Also tu es nicht.

+0

@NiklasB. es verletzt die Beschränkungen des Zuweisungsoperators: nicht streng konform. Siehe C99, 6.5.16.1p1 – ouah

1

Dies ist ein unglückliches Verhalten von gcc, und wenn jemand es behoben werden könnte, würden wir alle mit viel weniger Buggy-Software beschäftigen. Leider fehlt es am Willen, viele Dinge wie diese zu beheben. Das Einreichen eines Fehlerberichts würde nicht schaden.

+1

Warum ist es ein Fehler? Der Standard erfordert, dass der Compiler eine Diagnose ausgibt. –

+0

Tatsächlich habe ich übersehen, dass es die Anforderungen des Standards technisch erfüllte, indem ich eine Warnung ausgab. Persönlich glaube ich, dass der Compiler Programme mit Constraints-Verletzungen wie dieser ablehnen sollte, besonders wenn es keine korrekte/legitime Verwendung für das Konstrukt gibt. –

+0

'gcc' ist aus Kompatibilitätsgründen mit alten Programmen sehr permissiv, aber ich finde es auch in vielen Fällen zu freizügig. – ouah

Verwandte Themen