2016-10-30 3 views
0

So habe ich eine Funktion, die einen Zeiger auf ein Element in einem Array A zurückgibt. Ich habe eine andere Funktion, die diesen Zeiger als Parameter verwendet. Allerdings brauche ich diese Funktion, um mit der Möglichkeit umgehen zu können, dass ihr ein völlig beliebiger Zeiger übergeben wird.Überprüfen, ob Zeiger auf gegebenes Array zeigt

Gibt es eine Möglichkeit zu erkennen, ob ein Zeiger irgendwo innerhalb einer Struktur zeigt? In diesem Fall ist mein Array A?

Ich habe ähnliche Fragen in Bezug auf C++ gesehen, aber nicht mit C.

+0

Es gibt wahrscheinlich eine andere Frage, die das fragt. Sorta. Der Standard sagt nicht, dass es funktioniert, aber wenn Sie den Array-Start, die Anzahl der Elemente und die Größe jedes Elements sowie den angegebenen Zeiger kennen, können Sie feststellen, ob der angegebene Zeiger zwischen den Werten liegt Start und das Ende des Arrays.Das Problem ist, wenn der Zeiger außerhalb des Bereichs liegt, wird nicht garantiert, dass die Vergleiche nach dem Standard funktionieren, obwohl heutzutage meistens auf nicht segmentierten Maschinen (die meisten) tatsächlich funktioniert. –

+0

Wenn Sie mit Arrays arbeiten, warum erhalten Sie keine Offsets? Ich meine, eine einfache Ganzzahl, die als Index verwendet wird. So sparen Sie sich die Zugehörigkeitsprüfung. –

Antwort

3

Der einzige tragbare Weg besteht darin, einen Gleichheitstest für alle möglichen gültigen Werte für den Zeiger zu verwenden. Zum Beispiel:

int A[10]; 

bool points_to_A(int *ptr) 
{ 
    for (int i = 0; i < 10; ++i) 
     if (ptr == &A[i]) 
      return true; 

    return false; 
} 

beachten, dass ein Vergleichsoperator (zB <) oder Subtraktion, mit zwei Zeigern undefinierten Verhalten, wenn nicht die zwei Zeiger auf die Elemente des gleichen Array tatsächlich tun Punkt ist (oder eine über das Ende) .

+0

Clever! Das beseitigt die Warnungen – Bob

+0

'int array [100000];' ... Autsch! Aber das ist, was der Standard sagt, wird funktionieren. –

+0

Es ist auch erwähnenswert, dass das Subtrahieren von Zeigern (zum Beispiel 'ptr - A') auch undefiniertes Verhalten ergibt, es sei denn, beide Zeiger stammen aus demselben Array oder außer in C++. –

1

In Abschnitt §6.5.8 Relationale Operatoren, der C11-Standard (ISO/IEC 9899: 2011) sagt:

Wenn zwei Zeiger verglichen werden, hängt das Ergebnis von den relativen Positionen im Adressraum der Objekte ab, auf die verwiesen wird. Wenn zwei Zeiger auf Objekttypen beide auf das gleiche Objekt zeigen oder beide hinter das letzte Element des gleichen Array-Objekts zeigen, vergleichen sie das Gleiche. Wenn die Objekte, auf die verwiesen wird, Mitglieder desselben Aggregatobjekts sind, vergleichen Zeiger auf später deklarierte Strukturelemente größer als Zeiger auf zuvor in der Struktur deklarierte Elemente, und Zeiger auf Arrayelemente mit größeren tiefgestellten Werten vergleichen größere als Zeiger auf Elemente desselben Arrays mit niedrigeren Indexwerten. Alle Zeiger auf Mitglieder desselben Union-Objekts sind gleich. Wenn der Ausdruck P auf ein Element eines Array-Objekts zeigt und der Ausdruck Q auf das letzte Element desselben Array-Objekts zeigt, vergleicht der Zeigerausdruck Q+1 größer als P. In allen anderen Fällen ist das Verhalten nicht definiert.

Wenn Sie wissen, dass der Zeiger innerhalb der Reichweite des Arrays ist, dann funktionieren Vergleiche. Wenn der Zeiger außerhalb des Bereichs liegt, können Sie nicht sicher sein, dass die Vergleiche funktionieren. In der Praxis ist dies normalerweise der Fall, aber der Standard besagt ausdrücklich, dass der Vergleich zu undefiniertem Verhalten führt.

anzumerken, dass für ein Array SomeType array[20];, die Adresse &array[20] garantiert gültig zu sein und zuverlässig mit jeder Adresse von &array[0] durch &array[19] zu vergleichen. Sie müssen entscheiden, ob Sie das in Ihrem Array zählen möchten.

Vorbehaltlich der Beobachtung, dass der Standard garantiert nicht, dass es funktionieren wird, dann können Sie zwei int Zeiger vergleichen:

int within_int_array(int *array, size_t num_ints, int *ptr) 
{ 
    return ptr >= array && ptr < array + num_ints; 
} 

In diesen Tagen sollten Sie immer vorsichtig sein, nicht definiertes Verhalten aufruft. Compiler machen widerliche Dinge mit Programmen, die undefiniertes Verhalten verwenden, und technisch gesehen haben Sie keinen Rückgriff, da der Standard "undefiniertes Verhalten" sagt.

+0

In Bezug auf Ihren früheren Kommentar zu großen [~ 100000] -Arrays: Wenn Sie häufig mit einem Array testen mussten, konnten Sie nicht alle gültigen Zeiger auf das Array auf "uintptr_t" umwandeln und eine Hash-Tabelle erstellen. Um dann herauszufinden, ob ein Zeiger "p" auf ein Element des Arrays zeigt, könnten Sie "p" in "uintptr_t" umwandeln, das Ergebnis hashen und die Tabelle überprüfen. Oder ist das nur eine schlechte Idee? –

+1

@DavidBowling: Es könnte (eine Hash-Tabelle, oder etwas ähnliches) verwendet werden, aber ich kann nicht helfen, aber ich denke, dass es besser wäre zu wissen, wo Ihre Zeiger zeigen, als so viel Infrastruktur zu benötigen. –

Verwandte Themen