Kann ich tun, arithmetische Operationen auf void * - Zeiger in C?
ist diese gültig
void *p = &X; /* some thing */
p += 12;
und wenn ja, was bedeutet p nun?
Ich habe (Dritten) code, der dies tut (und fehlerfrei kompiliert wird) und meine Vermutung ist, dass die void * behandelt wurde, als ein char *. Mein treuer K&R ist stumm(ish) auf das Thema
EDIT: Meine kleine test-app läuft wunderbar auf gcc 4.1.1 und behandelt void * als char *. Aber g++ barfs
Ich weiß, wie man es richtig machen. Ich muss wissen, ob ich diese sauber code-Basis zu finden, alle die Plätze, fertig.
BTW gcc -pedantic wirft eine Warnung
Zusammenfassung:
Den C-spec ist mehrdeutig. Es sagt, dass in Bezug auf die Darstellung und Verwendung als Funktionsparameter void* =char*. Aber es ist still in Bezug auf Zeiger-Arithmetik.
- gcc (4) erlaubt es und behandelt es als
char * - g++ weigert sich, es
- gcc -pedantic warnt davor, es
- vs2010-c-und c++
verweigert er diese,
InformationsquelleAutor pm100 | 2010-10-25
Du musst angemeldet sein, um einen Kommentar abzugeben.
Es hängt davon ab, compiler. Diejenigen, die es betrachten, sizeof(*(void *)) als 1.
EDIT: es geht nur bei void-Zeiger Arithmetik. Es hätte keinen Sinn, wobei in diesem Fall die Schritte von sizeof(int) oder von 0. Die gemeinsamen Erwartungen von jemandem, der es verwendet, wäre der kleinste mögliche Schritt.
sizeof(void) == 1
... nicht zurechnungsfähig.Vielleicht für kleine Werte von 1.
danke für die Verschwendung ein paar Minuten aus meinem Tag, als ich saß in meinem Stuhl, hilflos zu lachen 🙂
Für spätere Leser: GCC Auffassung
sizeof void == 1
InformationsquelleAutor ruslik
Nein das ist nicht legal. Ein
void*
kann nicht willkürlich erhöht. Es muss gewirkt werden, um eine bestimmte Art erste.Wenn Sie erhöhen wollen es durch eine bestimmte Anzahl von bytes, dann ist dies die Lösung, die ich verwenden.
Den
char
Typ ist praktisch, denn es hat eine definierte Größe von 1 byte.BEARBEITEN
Es ist interessant, dass es läuft auf gcc mit einer Warnung. Getestet habe ich auf Visual Studio 2010 und überprüft, dass es nicht kompilieren. Meinem begrenzten Verständnis der Norm würde sagen, dass gcc in der Fehler hier. Können Sie fügen Sie die folgende Zusammenstellung flags
-pedantic wirft eine Warnung. kompilieren als c++ - fatals es
Ich bin immer noch verwirrt, wie die Inkrementierung
void*
könnte legal in C überhaupt. Es ist sicherlich scheint nicht tragbar.Ich bin genauso überrascht wie Sie sind, und warten noch auf eine endgültige Antwort auf diese.
Nein, ich denke nicht so. Ich habe nicht wirklich überprüft den text für den Inkrement-operator, aber sicherlich der text, der für die Additions-operator spricht nur über Zeiger auf Objekt-Typen, in der Erwägung, dass
void
ist ein unvollständiger Typ ist. So((void*)p) + 12;
ist eine Verletzung der Sprache, die Zwänge (ungültige Programm). MSVC ist daher richtig, ihn abzulehnen, und GCC ist richtig, es zu geben in der Implementierung definierte Semantik und kompilieren Sie es mit einer Warnung.InformationsquelleAutor JaredPar
Zitat aus der spec:
Einen Zeiger auf void wird kein Zeiger auf ein Objekt-Typ, wie pro diese Auszüge:
Daher, Zeiger-Arithmetik ist nicht definiert für Zeiger auf void-Typen.
gcc -pedantic
nur eine Warnung, sondern eine Diagnose dennoch.InformationsquelleAutor dreamlax
Ihre Vermutung ist korrekt.
In der standard ISO C99", Abschnitt 6.2.5, Absatz 26, erklärt, dass void-Zeiger und Zeichenketten Zeiger haben die gleiche Darstellung und alignment-Anforderungen (Umschreibung).
Und nicht definiert bedeutet, dass der compiler kann tun, was zum Teufel es will, einschließlich der Verwendung einer Elementgröße von
1
.Ja, vereinbart. Ich missverstanden, Fußnote 39. In 6.3.2.3 ABS 1 heißt es, dass void * umgewandelt werden kann, an/aus, nichts mit der Straffreiheit. Da es erforderlich ist, um die gleichen Eigenschaften wie "char *" es scheint logisch, dass es implizit in einem char * durch den compiler. Wie gesagt, ich denke, es ist wirklich schlechte Praxis zu manipulieren void * in dieser Weise.
definiert" bedeutet, aber dies ist kein Undefiniertes Verhalten, es ist eine Verletzung der Sprache, die Zwänge (die motivation ist, dass die Beschränkung auf die Typen der Operanden, nicht Ihre Werte; wir wissen, dass es eine Einschränkung wegen der großen überschrift "Einschränkungen" unmittelbar davor ;-)). Constraint-Verletzung führen muss, eine Diagnose. Die, mit
-pedantic
es tut, also kein Schaden. GCC ohne-pedantic
ist nicht, und erhebt nicht den Anspruch, eine standard-Bestätigung der C-compiler sowieso.InformationsquelleAutor Marc Butler
Haben möchten Sie vielleicht einen Blick auf die top-stimmten Antwort für diese Frage
Pointer Arithmetik void-Zeiger in C
InformationsquelleAutor VikramW
Ich glaube nicht, dass Sie können, weil Sie nicht wissen, seine Art, kann daher nicht versuchen, die korrekte Anzahl von bytes.
Cast es zu einer Art ersten, also
(int)
.int
wenn dann die+= 12
im wesentlichen interpretiert als+= sizeof(int)*12
im Hinblick darauf, wie viele bytes wurden tatsächlich aufgenommen. Dies scheint nicht wie das beabsichtigte Verhalten.Würde es funktionieren, wenn, die Zeiger haben eine integer-obwohl?
wieder hängt, die auf Vorsatz. Wenn das Absicht war, um es zu bewegen 12 Elemente nach vorne, dann ja. Wenn das Absicht war, um es zu bewegen 12 bytes nach vorne, dann Nein. Schwer zu Lesen der Absicht, sich aus der Frage, aber meine Vermutung ist, dass der OP will kein Inkrement 12 bytes.
In der Regel macht es Sinn zu casten (void *) in einen anderen Zeigertyp, so zum Beispiel (int *) oder (char *) oder (struct Foo *), oder eine Implementierung abhängige integer-Typ, wie (size_t), obwohl im letzteren Fall das resultierende Verhalten ist nicht standardisiert in irgendeiner Weise.
InformationsquelleAutor alex