webentwicklung-frage-antwort-db.com.de

Wie kann ich direkt zu einer Zeigerposition wechseln, ohne den ++ - Operator zu verwenden?

Ich arbeite mit einem Zeiger auf eine Struktur. Ich möchte wissen, ob es möglich ist, direkt an eine bestimmte Position zu gelangen, ohne den Operator ++ zu verwenden.

#include <stdio.h>
#include <stdlib.h>

#define ARRAY_SIZE 10

struct dummy{
    int id;
    char buffer[10];
};

typedef struct dummy dummy_struct;

int main()
{
    int i=0;
    dummy_struct *ds = malloc(sizeof(dummy_struct)*ARRAY_SIZE);
    dummy_struct *iterator = ds;

    for(i=0;i<ARRAY_SIZE;i++)
    {
        iterator->id = i;
        sprintf(iterator->buffer,"%d",i);
        iterator++;
    }

    iterator = ds;

    for(i=0;i<ARRAY_SIZE;i++)
    {
        printf("%d:%s:%p\n",iterator->id,iterator->buffer,iterator);
        iterator++;
    }

    // I want to access directly to 5th position
    iterator = ds + (sizeof(dummy_struct)*5);
    printf("5th position %d:%s:%p\n",iterator->id,iterator->buffer,iterator);

    return 0;
}

Diese Aussage

iterator = ds + (sizeof(dummy_struct)*5);

funktioniert nicht. Ich werde jeden Vorschlag zu schätzen wissen.

9
Rubén Pozo

Nun, Zeigerarithmetik würdigt den Datentyp !!

iterator = ds + 5;

wird die Arbeit erledigen.

Um dies zu erläutern, wird der obige Ausdruck einen Zeiger erzeugen, indem er in Bytes fünfmal mit der Größe des Typs für ds multipliziert wird. Das ist dasselbe wie &(ds[5]).

Um der Vollständigkeit halber zu erklären, warum iterator = ds + (sizeof(dummy_struct)*5); falsch ist, versuchen Sie hier im Wesentlichen, den Zeiger auf ein Element mit Index als (sizeof(dummy_struct)*5 zu verschieben, der sich außerhalb der Grenzen befindet. Bitte beachten Sie, dass dies undefiniertes Verhalten !! hinweis unten

Zitieren C11, Kapitel §6.5.6/P8

Wenn ein Ausdruck, der einen Integer-Typ hat, zu einem Zeiger hinzugefügt oder von diesem abgezogen wird, hat das Ergebnis Den Typ des Zeigeroperanden. Wenn der Zeigeroperand auf ein Element von Eines Arrayobjekts zeigt und das Array groß genug ist, zeigt das Ergebnis auf einen Elementversatz von Des ursprünglichen Elements, so dass die Differenz der Subskripte des Die resultierenden und ursprünglichen Array-Elemente entsprechen dem ganzzahligen Ausdruck. Wenn der Ausdruck P auf Das i- te Element eines Array-Objekts zeigt, zeigen die Ausdrücke (P)+N (äquivalent N+(P)) und (P)-N (wobei N den Wert n hat) die i+n- und i−n_-ten Elemente des Array-Objekts , sofern sie vorhanden sind. [....]

und dann in Bezug auf das oben erwähnte undefinierte Verhalten, 

[....] Wenn sowohl der Zeiger-Operand Als auch das Ergebnis auf Elemente desselben Arrayobjekts oder auf ein Element hinter dem letzten Element des Arrayobjekts zeigen, darf die Auswertung kein Überlauf; Andernfalls ist das Verhalten undefiniert. Wenn das Ergebnis einen Punkt hinter das letzte Element des Array-Objekts zeigt, darf es Nicht als Operand eines unären *-Operators verwendet werden, der ausgewertet wird.


Davon abgesehen ist auch die printf()-Anweisung fehlerhaft. Sie haben zwei Konvertierungsspezifizierer, aber drei Argumente angegeben. Es ist nicht schädlich , aber nutzlos/sinnlos.

Verwandte, aus Kapitel §7.21.6.1/P2,

[...] Wenn das Format erschöpft ist, während Argumente bestehen bleiben, werden die überzähligen Argumente Ausgewertet (wie immer), werden aber ansonsten ignoriert. [...]

Anhand dieses Falls können Sie direkt verwenden

printf("5th position %d:%s:\n",ds[5].id,ds[5].buffer);
30
Sourav Ghosh

Das Verhalten von 

iterator = ds + (sizeof(dummy_struct) * 5);

ist undefined wenn Sie einen Zeiger hinter dem letzten Element des Arrays setzen. Sie setzen iterator tatsächlich auf weitere Elemente im Array, als Sie denken, um den Faktor sizeof(dummy_struct)! Tu das nicht.

Die Sprache ermöglicht die Verwendung der Notation iterator = ds + 5;. Diese idiomatische Zeigerarithmetik fügt 5 Lose sizeof(dummy_struct) zur Adresse iterator hinzu. Der Compiler nimmt also die sizeof-Einstellung für Sie vor. Das ist ein Grund, warum die Zeigerarithmetik so mächtig ist.

Beachten Sie schließlich, dass *(ds + 5) äquivalent zu ds[5] ist. Ich finde, letzteres bietet mehr Klarheit bei der Arbeit mit Arrays.

8
Bathsheba

Anscheinend versuchen Sie, den Zeiger iterator auf das 5th-Element des Arrays ds zu richten. Diese Aussage wird jedoch zu einem falschen Ergebnis führen:

iterator = ds + (sizeof(dummy_struct)*5);

Das Ergebnis von sizeof(dummy_struct)*5 ergibt die Gesamtgröße aller Elemente der Struktur dummy_struct, multipliziert mit 5, die zu der mit ds referenzierten Adresse addiert und iterator zugewiesen wird. So kann iterator auf einen Speicherplatz verweisen, den Ihr Programm nicht besitzt. Sie müssen tun:

iterator = ds + 5;

Oder Sie können auch:

iterator = &ds[5];
2
H.S.