Ist es eine gute Idee, Zeiger zu typedef?

Lesezeit: 10 Minuten

Ist es eine gute Idee Zeiger zu typedef
Unbekannt

Ich habe etwas Code durchgesehen und festgestellt, dass die Konvention darin bestand, Zeigertypen wie zu ändern

SomeStruct* 

hinein

typedef SomeStruct* pSomeStruct;

Gibt es einen Verdienst dafür?

  • Es ist in C üblich. Weil Sie versuchen, die Tatsache zu verbergen, dass es sich um einen Zeiger handelt. Dies ist das Objekt, das Sie an alle Schnittstellen in einer Bibliothek übergeben. In C++ ist es nicht üblich und es wird davon abgeraten, obwohl es nicht ungewöhnlich ist.

    – Martin York

    15. April 2009 um 4:37 Uhr

  • Ein interessanter Artikel zu diesem allgemeinen Thema: Gespräche: Ein Mittsommernachtswahnsinn Siehe auch Linux-Kernel-Codierungsstil für eine extreme Ansicht von ‘keine Typedef-Zeiger (und keine Typedefs für Strukturen oder Unions)’.

    – Jonathan Leffler

    15. Januar 2019 um 5:49 Uhr

  • @MartinYork Man könnte hinzufügen, dass es in C++ nicht benötigt wird, da es die Weitergabe von Referenzen unterstützt

    – klutt

    11. Mai 2021 um 9:16 Uhr

  • @klutt In C++ verwendet man sowieso eher Methoden als Funktionen, damit das versteckte Objekt (this) immer da ist.

    – Martin York

    11. Mai 2021 um 16:06 Uhr

1647289214 808 Ist es eine gute Idee Zeiger zu typedef
Artelius

Dies kann sinnvoll sein, wenn der Zeiger selbst als “Black Box” betrachtet werden kann, also als Datenelement, dessen interne Repräsentation für den Code irrelevant sein soll.

Im Wesentlichen, wenn Ihr Code es will noch nie Dereferenzieren Sie den Zeiger, und Sie übergeben ihn einfach an API-Funktionen (manchmal als Referenz), dann reduziert die Typedef nicht nur die Anzahl von *s in Ihrem Code, sondern suggeriert dem Programmierer auch, dass man sich nicht wirklich mit dem Zeiger einmischen sollte.

Dies macht es auch einfacher, die API in Zukunft bei Bedarf zu ändern. Wenn Sie beispielsweise auf die Verwendung einer ID anstelle eines Zeigers (oder umgekehrt) umstellen, wird vorhandener Code nicht beschädigt, da der Zeiger von vornherein nie dereferenziert werden sollte.

  • Beispiel aus der Praxis: In OS X macht das CoreFoundation-Framework ausgiebigen Gebrauch von dieser Technik und bezeichnet sie als „undurchsichtige“ Datentypen.

    – hbw

    15. April 2009 um 3:32 Uhr

  • Auch in OS X: pthread_t ist ein undurchsichtiger Typ; Es ist typdefiniert, um ein Zeiger auf ein ‘struct _opaque_pthread_t’ zu sein, das selbst ein undurchsichtiges Array von Bytes ist.

    – Adam Rosenfield

    15. April 2009 um 4:42 Uhr

  • Gegenbeispiel: DATEI *fp? Eigentlich stimme ich Ihnen zu, aber es gibt genügend Präzedenzfälle für das Gegenteil.

    – Jonathan Leffler

    15. April 2009 um 4:56 Uhr

  • Wenn Sie dies tun, nennen Sie den undurchsichtigen Typ natürlich nicht “pFoo”.

    – MSalter

    15. April 2009 um 8:59 Uhr

  • @MattJoiner: der Grund FILE* wurde nicht als undurchsichtiger Zeiger typdefiniert, um Makros wie z getc() und putc() um die FILE-Struktur direkt zu manipulieren und den Funktionsaufruf-Overhead in den meisten Fällen zu vermeiden.

    – chqrlie

    18. August 2016 um 8:37 Uhr

Nicht in meiner Erfahrung. Ausblenden der ‘*‘ macht den Code schwer lesbar.

  • Keine Ahnung davon. Ich meine, wenn Sie einen Hinweis haben, sagen wir mal Device Und Sie typedef es zu Device_Ptr (anstatt verwenden zu müssen Device *) oder ähnlich ist es gut lesbar. Ich sehe viele ausgereifte und ziemlich große Bibliotheken, die das tun. Besonders in C++, wenn Sie Templates hinzufügen, kann dies Ihre Finger viel Tipparbeit ersparen.

    – rbaleksandar

    15. Februar 2017 um 12:49 Uhr

  • @rbaleksandar wieder ist es in Ordnung, wenn Device* ein undurchsichtiger Handle ist.

    – Alex D

    6. April 2018 um 20:18 Uhr

  • Als C n00b denke ich, dass die Zeigersyntax von C ein Gräuel ist – nur von den unglücklichen Seelen gemocht, die bereits über 10 Jahre damit verbracht haben, sie zu mögen. ich werde nehmen myTypePtr oder myTypeRef jeden Tag über diesen Stern. 😛

    – Christoffer Bubach

    30. Juni 2020 um 0:37 Uhr

1647289215 759 Ist es eine gute Idee Zeiger zu typedef
Jonathan Leffler

Das einzige Mal, dass ich einen Zeiger innerhalb der Typedef verwende, ist, wenn ich mich mit Zeigern auf Funktionen befasse:

typedef void (*SigCatcher(int, void (*)(int)))(int);

typedef void (*SigCatcher)(int);

SigCatcher old = signal(SIGINT, SIG_IGN);

Ansonsten finde ich sie eher verwirrend als hilfreich.


Die durchgestrichene Deklaration ist der richtige Typ für einen Zeiger auf die signal() Funktion, nicht des Signalfängers. Es könnte klarer gemacht werden (mit der korrigierten SigCatcher oben eingeben), indem Sie schreiben:

 typedef SigCatcher (*SignalFunction)(int, SigCatcher);

Oder, um die zu erklären signal() Funktion:

 extern SigCatcher signal(int, SigCatcher);

Das ist ein SignalFunction ist ein Zeiger auf eine Funktion, die zwei Argumente (an int und ein SigCatcher) und gibt a zurück SigCatcher. Und signal() selbst ist eine Funktion, die zwei Argumente (an int und ein SigCatcher) und gibt a zurück SigCatcher.

  • Funktioniert diese Typedef mit weniger Interpunktion? “typedef void SigCatcher(int, void

    (int))(int)”

    – Sigissaft

  • 18. April 2009 um 0:13 Uhr

    Nein; gcc sagt “Fehler: SigCatcher als Funktion deklariert, die eine Funktion zurückgibt”.

    – Jonathan Leffler

  • 18. April 2009 um 4:44 Uhr Ich kam gerade als noch einfachere typdefinierte Deklaration von signal () rüber

    freebsd.org/cgi/man.cgi?query=signal

    – Sigissaft

  • 6. November 2010 um 20:17 Uhr sig_t @Sigjuice: Auch ohne auf die BSD-Seite zu gehen (was ich erst tat, nachdem ich das Material bearbeitet hatte), sah ich große Probleme mit meiner Antwort, die jetzt behoben sind. Und was BSD anruft SigCatcherpasst zu meinem signal() und ja, es vereinfacht die Deklaration von

    enorm.

    – Jonathan Leffler

  • 6. November 2010 um 21:20 Uhr

    kühl. Die äquivalente Deklaration mit dem expliziten * sieht meiner Meinung nach gar nicht so schlecht aus. typedef void SigCatcher(int); extern SigCatcher *signal(int, SigCatcher *);

    – Sigissaft

6. November 2010 um 22:20 Uhr

int* pointer1, pointer2;

Dies kann Ihnen helfen, einige Fehler zu vermeiden. Zum Beispiel in folgendem Code: Zeiger2 ist keinint * es ist einfachint

typedef int* pInt;
pInt pointer1, pointer2;

. Aber mit typedefs wird das nicht passieren: Beide sind int *

1647289215 130 Ist es eine gute Idee Zeiger zu typedef
jetzt.

cmaster – monica wieder einsetzen

Meine Antwort ist ein klares „Nein“.

Warum? * Nun, zunächst tauscht man einfach ein einzelnes Zeichen aus pfür ein weiteres einzelnes Zeichen . Das ist Null

gewinnen. Dies allein sollte Sie davon abhalten, da es immer schlecht ist, zusätzliche Dinge zu tun, die sinnlos sind. Zweitens, und das ist der wichtige Grund, * derträgt eine Bedeutung, die sich nicht gut verstecken lässt

void foo(SomeType bar);

void baz() {
    SomeType myBar = getSomeType();
    foo(myBar);
}

. Wenn ich so etwas an eine Funktion übergebe myBar Ich erwarte nicht die Bedeutung von foo()durch Übergabe an geändert werden foo() . Immerhin übergebe ich nach Wert, also myBar sieht immer nur eine Kopie von SomeType rechts? Nicht wenn

wird aliasiert, um eine Art Zeiger zu bedeuten! Vor allem, wenn dieser Zeiger als Verweis auf eine Art Objekt fungiert, dessen Wert im Grunde die Bedeutung des Zeigers ist: Es ist mir egal, dass sich der Zeiger selbst nicht ändert (aufgrund des Pass-by-Werts), ich bin daran interessiert ob sich das Objekt ändert oder nicht (das Objekt hinter dem Zeiger).

Dies gilt sowohl für C-Zeiger als auch für intelligente C++-Zeiger: Wenn Sie die Tatsache verbergen, dass es sich um Zeiger auf Ihre Benutzer handelt, stiften Sie völlig unnötige Verwirrung. Aliasieren Sie Ihre Zeiger also bitte nicht. (Ich glaube, die Gewohnheit, Pointer-Typen zu definieren, ist nur ein fehlgeleiteter Versuch, zu verbergen, wie viele Sterne man als Programmierer hat http://wiki.c2.com/?ThreeStarProgrammer

  • .) void *vp=/*...*/; foo(vp); +1. Ein weiterer Grund ist, dass es keinen Typsystemschutz geben wird foo(0);oder

    . (Typedefs für Aufzählungen und numerische Typedefs für Dinge, die niemals als Zahlen erscheinen sollten, haben ähnliche Probleme).

    – PSkočik


  • 10. November 2018 um 21:06 Uhr Auch wenn Sie die bestehen Zeiger myBar zu einer Funktion, dem Zeiger selbst wird immer noch kopiert, auch wenn die Daten, auf die es verweist, nicht kopiert werden. Also die Wert myBar von foo(das ist eine Adresse) kann immer noch nicht geändert werden aber der Wert wies auf myBar durch

    kann.

    – Aposhian

  • 11. August 2021 um 15:21 Uhr struct _fraction @ Aposhian Ja. Damit? – Mein Punkt ist, dass ein Zeiger normalerweise als Proxy für ein Objekt im Speicher dient. Die Semantik des Zeigers ist so ziemlich die Semantik des Objekts dahinter, und diese kann von jeder Funktion geändert werden, die den Zeiger empfängt. Zum Beispiel, wenn Sie einen Typ hatten Fractionund seinen Zeiger auf typdefiniert Fraction a = fraction(84, 2); printFrac(a); doSomething(a); printFrac(a); die Aussagen Fraction* a = fraction(84, 2); könnte zu verwirrenden Ausgaben führen. Mit doSomething(a) es ist klar, dass a kann die Bedeutung von ändern

    durch Objektwechsel.

    – Cmaster – Wiedereinsetzung von Monica

  • 11. August 2021 um 15:40 Uhr Ja, du hast recht. Und ich stimme zu, dass Typedef-ing-Zeiger im Allgemeinen eine Verschleierung sind. Ich möchte nur nicht, dass jemand, der dies liest, das verwechselt Bedeutung/Semantik eines Zeigers und seinerWert

    , die getrennt und verschieden sind. Diesen Unterschied zu beachten ist entscheidend, wenn Zeigervariablen neu zugewiesen oder Zeiger-zu-Zeiger verwendet werden.

    – Aposhian


  • 11. August 2021 um 20:01 Uhr

    @ Aposhian Ah, jetzt verstehe ich. Nun, ich habe an der fraglichen Stelle einige Worte hinzugefügt, in der Hoffnung, meine Bedeutung klarer zu machen. Danke für den Hinweis.

    – Cmaster – Wiedereinsetzung von Monica

Ist es eine gute Idee Zeiger zu typedef
11. August 2021 um 20:18 Uhr

JaredPar

Das ist eine Frage des Stils. Sie sehen diese Art von Code sehr häufig in den Windows-Header-Dateien. Obwohl sie dazu neigen, die Version in Großbuchstaben zu bevorzugen, anstatt ein kleines p voranzustellen.

typedef stl::map<stl::wstring,CAdapt<CComPtr<IFoo>> NameToFooMap;

  • Persönlich vermeide ich diese Verwendung von typedef. Es ist viel klarer, wenn der Benutzer explizit sagt, dass er ein Foo* will, als ein PFoo. Typedefs sind heutzutage am besten geeignet, um STL lesbar zu machen 🙂 void *vp=/*...*/; foo(vp); +1. Ein weiterer Grund ist, dass es keinen Typsystemschutz geben wird foo(0);oder

    . (Typedefs für Aufzählungen und numerische Typedefs für Dinge, die niemals als Zahlen erscheinen sollten, haben ähnliche Probleme).

    – PSkočik


  • 10. November 2018 um 21:06 Uhr Auch wenn Sie die bestehen Zeiger myBar zu einer Funktion, dem Zeiger selbst wird immer noch kopiert, auch wenn die Daten, auf die es verweist, nicht kopiert werden. Also die Wert myBar von foo(das ist eine Adresse) kann immer noch nicht geändert werden aber der Wert wies auf myBar durch

    kann.

    – Aposhian

  • 11. August 2021 um 15:21 Uhr struct _fraction @ Aposhian Ja. Damit? – Mein Punkt ist, dass ein Zeiger normalerweise als Proxy für ein Objekt im Speicher dient. Die Semantik des Zeigers ist so ziemlich die Semantik des Objekts dahinter, und diese kann von jeder Funktion geändert werden, die den Zeiger empfängt. Zum Beispiel, wenn Sie einen Typ hatten Fractionund seinen Zeiger auf typdefiniert Fraction a = fraction(84, 2); printFrac(a); doSomething(a); printFrac(a); die Aussagen Fraction* a = fraction(84, 2); könnte zu verwirrenden Ausgaben führen. Mit doSomething(a) es ist klar, dass a kann die Bedeutung von ändern

    durch Objektwechsel.

    – Cmaster – Wiedereinsetzung von Monica

  • 11. August 2021 um 15:40 Uhr Ja, du hast recht. Und ich stimme zu, dass Typedef-ing-Zeiger im Allgemeinen eine Verschleierung sind. Ich möchte nur nicht, dass jemand, der dies liest, das verwechselt Bedeutung/Semantik eines Zeigers und seinerWert

    , die getrennt und verschieden sind. Diesen Unterschied zu beachten ist entscheidend, wenn Zeigervariablen neu zugewiesen oder Zeiger-zu-Zeiger verwendet werden.

    – Aposhian


  • 11. August 2021 um 20:01 Uhr

    @ Aposhian Ah, jetzt verstehe ich. Nun, ich habe an der fraglichen Stelle einige Worte hinzugefügt, in der Hoffnung, meine Bedeutung klarer zu machen. Danke für den Hinweis.

    – Cmaster – Wiedereinsetzung von Monica

1647289216 520 Ist es eine gute Idee Zeiger zu typedef
11. August 2021 um 20:18 Uhr

Martin York

Es kommt (wie so viele Antworten) darauf an.

MYDB   db = MYDBcreateDB("Plop://djdjdjjdjd");

MYDBDoSomthingWithDB(db,5,6,7);
CallLocalFuc(db); // if db is not a pointer things could be complicated.
MYDBdestroyDB(db);

In C ist dies sehr verbreitet, da Sie versuchen, zu tarnen, dass ein Objekt ein Zeiger ist. Sie versuchen zu implizieren, dass dies das Objekt ist, das alle Ihre Funktionen manipulieren (wir wissen, dass es sich um einen Zeiger darunter handelt, aber es repräsentiert das Objekt, das Sie manipulieren).

Unter MYDB befindet sich wahrscheinlich ein Zeiger auf ein Objekt.
In C++ ist dies nicht mehr erforderlich.

MyDB   db("Plop://djdjdjjdjd");

db.DoSomthingWithDB(5,6,7);
CallLocalFuc(db);   // This time we can call be reference.
db.destroyDB();     // Or let the destructor handle it.

1003040cookie-checkIst es eine gute Idee, Zeiger zu typedef?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy