Was ist der Zweck des Schlüsselworts “volatile”, das in einem Array-Index erscheint?

Lesezeit: 4 Minuten

Benutzeravatar von msc
msc

Während ich cpreference durchsuchte, sah ich ein seltsames Typ-Array in Funktionsparametern wie diesem:

void f(double x[volatile], const double y[volatile]);

Also, was ist der Zweck der volatile Schlüsselwort, das in einem Array-Index erscheint? Was tut es?

  • Das Ziel dieser Syntax ist einfach, den Code unlesbar zu machen 😉 Ich werde das zu dem “niemals tun” in unseren Codierungsrichtlinien hinzufügen 🙂

    – Klaus

    19. November 2017 um 13:55 Uhr

Benutzeravatar von msc
msc

Das volatile Schlüsselwort wird verwendet, um einen Array-Typ eines Funktionsparameters zu deklarieren.

Hier, double x[volatile] ist äquivalent zu double * volatile x.

Das cpReferenz sagt:

In einer Funktionsdeklaration das Stichwort volatile kann innerhalb der eckigen Klammern erscheinen, die verwendet werden, um einen Array-Typ eines Funktionsparameters zu deklarieren. Es qualifiziert den Zeigertyp, in den der Array-Typ transformiert wird. Die folgenden beiden Deklarationen deklarieren dieselbe Funktion:

void f(double x[volatile], const double y[volatile]);

void f(double * volatile x, const double * volatile y);

Diese Syntax ist nur in der C-Sprache in Funktionsparametern gültig.

  • Die C++-Syntax macht noch weniger Sinn, als ich dachte, ich glaube, wir haben gerade einen neuen Höhepunkt der Hässlichkeit erreicht. Ich schlage hiermit vor, Alkohol von WG21-Sitzungen zu verbieten.

    – Matteo Italien

    19. November 2017 um 13:14 Uhr


  • @MatteoItalia Das ist keine C++-Syntax.

    Benutzer743382

    19. November 2017 um 13:56 Uhr

  • @hvd: mein vorschlag soll dann auf WG14 geroutet werden.

    – Matteo Italien

    19. November 2017 um 14:19 Uhr

  • @MatteoItalia: C bietet noch mehr Hässlichkeit, da es eine Ausnahme von der Regel gibt: gegeben int foo(int myArray[static 5])das static Qualifizierer bedeutet nicht, dass das Array statisch ist, sondern garantiert, dass der gesamte Speicher aus myArray[0]..myArray[4] kann vom Compiler als ohne Seiteneffekte lesbar angesehen werden.

    – Superkatze

    19. November 2017 um 19:29 Uhr

  • @supercat Die Garantie ist in der Tat das x Zeiger auf ein Array-Element und die Ausdrücke x[0] durch x[4] bezeichnen andere Elemente desselben Arrays (dh sie lesen nicht außerhalb der Grenzen dieses Arrays). Der Begriff “Nebenwirkungen” hat eine besondere Bedeutung in C

    – MM

    19. November 2017 um 22:32 Uhr


Benutzeravatar von Matteo Italia
Matteo Italien

Im Allgemeinen erlaubt diese C-Funktion (und nur C!) die Angabe eines beliebigen Typqualifizierers innerhalb der Array-Klammern; Das genaue Standardangebot lautet:

Eine Deklaration eines Parameters als ”array of type” soll auf ”qualified pointer to type” angepasst werden, wobei die Typqualifizierer (falls vorhanden) diejenigen sind, die in der angegeben sind [ and ] der Array-Typ-Ableitung. Wenn das Schlüsselwort static erscheint auch innerhalb der [ and ] der Array-Typ-Ableitung, dann muss für jeden Aufruf der Funktion der Wert des entsprechenden tatsächlichen Arguments den Zugriff auf das erste Element eines Arrays mit mindestens so vielen Elementen ermöglichen, wie durch den Größenausdruck angegeben.

(C99, §6.7.5.3, ¶7, Hervorhebung hinzugefügt)

Dies bedeutet, dass dies nicht nur darauf beschränkt ist volatileaber const und restrict sind ebenfalls erlaubt (vgl Geben Sie Qualifizierer ein§6.7.3 Abs. 1).

Der Sinn dieses Hacks besteht im Wesentlichen darin, dass Sie einen Typqualifizierer hinzufügen können zum Parameter (nicht zum Element des Arrays) und behalten dennoch die Array-Syntax für die Deklaration bei; Ohne diese Syntax sind Sie gezwungen, darauf zurückzugreifen, es als Zeiger zu schreiben (worauf es sowieso hinausläuft mit Ausnahme der static Fallfür die AFAIK keine äquivalente Zeigersyntax hat).

Ich vermute, dass die Idee hauptsächlich darin besteht, die Syntax für mehrdimensionale Arrays etwas weniger umständlich zu machen. Zitat aus §6.7.5.3 Abs. 21:

void f(double (* restrict a)[5]);
void f(double a[restrict][5]);
void f(double a[restrict 3][5]);

sind alle gleichwertig, aber 2 und 3 können etwas besser vermitteln, dass dies nicht nur ein Zeiger, sondern ein Array ist, und dennoch einen Platz zum Platzieren der restrict Qualifikation.

Außerdem scheint es, wie oben gesagt, keine Möglichkeit zu geben, so etwas zu haben

void f(double a[restrict static 3][5]);

(was “auch angibt, dass das entsprechende Argument a in jedem Aufruf an f muss ein Nicht-Null-Zeiger auf das erste von mindestens drei Arrays von 5 Doubles sein”, ebenda) mit der “normalen” Zeigersyntax.

Trotzdem würde ich mich von dieser Syntax fernhalten; Es ist extrem obskur und wird selten verwendet (ich glaube nicht, dass ich jemals einen Typqualifizierer zu einem Array hinzufügen musste Parameter – wieder der Parameter selbst, nicht der Elementtyp; restrict ist der einzige Anwendungsfall, der sinnvoll sein kann) – und nicht nach C++ portierbar (was im Allgemeinen relevant ist, wenn Sie eine Bibliothek schreiben).

  • Wenn volatile in Ihrem Code sinnvoll sein kann, ist dies sehr nützlich.

    – edmz

    19. November 2017 um 19:13 Uhr

  • @edmz: a volatile Parameter ist auf jeden Fall bizarr… volatile bedeutet, dass der Compiler wachsam bleiben sollte, dass sich der dort gespeicherte Wert hinter seinem Rücken ändern kann (zB aufgrund von Interrupt-Handlern, Signalen oder anderem Hardware-Zeug); Dies ist im Allgemeinen entweder Zeug, das von mehreren Akteuren gemeinsam genutzt wird (z. B. eine globale Variable) oder etwas an einer festen Stelle im Speicher, das der Hardware / dem Betriebssystem bekannt ist. Ein Parameter ist stattdessen per Definition lokal für die Funktion, daher verstehe ich nicht wirklich, welche Art von Nützlichkeit dies könnte volatile habe hier.

    – Matteo Italien

    19. November 2017 um 21:40 Uhr

  • @edmz: (denk daran: double x[volatile] meint double * volatile xso ist es x das ist volatilenicht worauf es hindeutet)

    – Matteo Italien

    19. November 2017 um 21:42 Uhr

  • @MatteoItalia: modify_asynchronously(&a);

    – Nate Eldredge

    20. November 2017 um 1:10 Uhr


  • @NateEldredge: kopiere es nach a volatile lokale Variable vorher und verwenden Sie sie stattdessen.

    – Matteo Italien

    20. November 2017 um 6:08 Uhr


1401850cookie-checkWas ist der Zweck des Schlüsselworts “volatile”, das in einem Array-Index erscheint?

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

Privacy policy