Mehrfachbelegung in einer Zeile

Lesezeit: 5 Minuten

Benutzer-Avatar
riskant

Ich stoße gerade auf die Anweisung in eingebettetem c (dsPIC33)

sample1 = sample2 = 0;

Würde dies bedeuten

sample1 = 0;

sample2 = 0;

Warum schreiben sie es so? Ist das gute oder schlechte Codierung?

  • Mögliches Duplikat von Zwei Gleichheitszeichen in einer Zeile?

    – Baum mit Augen

    5. März 2019 um 22:56 Uhr

Denken Sie daran, dass die Zuweisung von rechts nach links erfolgt und dass es sich um normale Ausdrücke handelt. Aus Sicht des Compilers also die Zeile

sample1 = sample2 = 0;

ist das gleiche wie

sample1 = (sample2 = 0);

was dasselbe ist wie

sample2 = 0;
sample1 = sample2;

Das ist, sample2 wird dann Null zugeordnet sample1 wird der Wert von zugewiesen sample2. In der Praxis dasselbe wie das Zuweisen von beiden zu Null, wie Sie es erraten haben.

  • Es ist wahrscheinlich erwähnenswert, dass dieser Ausdruck keine Sequenzierung enthält. Was bedeutet, dass es nicht richtig ist, dies anzunehmen sample2 zuerst zugewiesen wird, und dass der Wert zugewiesen wird sample1 wird buchstäblich abgelesen sample2. Genauer gesagt, sample1 Wert zugeordnet wird 0 umgewandelt in Typ von sample2. Und der Auftrag an sample1 kann tatsächlich vor der Zuweisung passieren sample2.

    – AnT steht zu Russland

    14. Oktober 2013 um 8:10 Uhr


  • Vielen Dank für die Antwort, ich würde sample1=sample2=0 im Namen des Lesbarkeits- und Sequenzierungsproblems vermeiden, wie in AndreyT hervorgehoben.

    – riskant

    15. Oktober 2013 um 7:07 Uhr

  • Dem würde ich das hinzufügen sample2=0 gibt einen rvalue zurück, der gleich dem in zugewiesenen Wert ist sample2. Es ist also eine Zuweisungsanweisung und hat zusätzlich einen Rückgabewert, der dem zugewiesenen Wert entspricht. Dieser zurückgegebene Wert (rvalue) wird zugewiesen sample1.

    – Hasem

    30. Juli 2015 um 3:34 Uhr

Benutzer-Avatar
AnT steht zu Russland

Formal für zwei Variablen t und u des Typs T und U beziehungsweise

T t;
U u;

die Zuordnung

t = u = X;

(wo X ein Wert ist) wird interpretiert als

t = (u = X);

und entspricht einem Paar unabhängiger Zuweisungen

u = X;
t = (U) X;

Beachten Sie, dass der Wert von X soll Variable erreichen t “als ob” es die Variable durchlaufen hat u zuerst, aber es gibt keine Voraussetzung dafür, dass es buchstäblich so geschieht. X muss einfach in type of konvertiert werden u vor der Zuweisung t. Der Wert muss nicht zugewiesen werden u zuerst und dann kopiert von u zu t. Die beiden oben genannten Zuweisungen sind eigentlich nicht sequenziert und können in beliebiger Reihenfolge erfolgen, was bedeutet, dass

t = (U) X;
u = X;

ist auch ein gültiger Ausführungszeitplan für diesen Ausdruck. (Beachten Sie, dass diese Sequenzierungsfreiheit spezifisch für die C-Sprache ist, in der das Ergebnis einer Zuweisung ein R-Wert ist. In C++ wird die Zuweisung zu einem L-Wert ausgewertet, was erfordert, dass “verkettete” Zuweisungen sequenziert werden.)

Es gibt keine Möglichkeit zu sagen, ob es sich um eine gute oder schlechte Programmierpraxis handelt, ohne mehr Kontext zu sehen. In Fällen, in denen die beiden Variablen eng miteinander verbunden sind (z x und y Koordinate eines Punktes), sie mit “verketteter” Zuweisung auf einen gemeinsamen Wert zu setzen, ist eigentlich eine absolut gute Praxis (ich würde sogar “empfohlene Praxis” sagen). Wenn die Variablen jedoch völlig unabhängig voneinander sind, ist es definitiv keine gute Idee, sie in einer einzigen “verketteten” Zuweisung zu mischen. Vor allem, wenn diese Variablen unterschiedliche Typen haben, was zu unbeabsichtigten Konsequenzen führen kann.

  • Ich glaube, der Standard gibt an, dass der Effekt ist nicht als ob die Variable zuerst durchgeschrieben wurde – eine Unterscheidung, die äußerst wichtig sein könnte, wenn die fragliche Variable dies ist volatile.

    – Superkatze

    18. Mai 2015 um 17:30 Uhr

Ich denke, es gibt keine gute Antwort auf C-Sprache ohne tatsächliche Assembly-Liste 🙂

Also für ein vereinfachtes Programm:

int main() {
        int a, b, c, d;
        a = b = c = d = 0;
        return a;
}

Ich habe diese Assembly (Kubuntu, gcc 4.8.2, x86_64) mit -O0 Option natürlich 😉

main:
        pushq   %rbp
        movq    %rsp, %rbp

        movl    $0, -16(%rbp)       ; d = 0
        movl    -16(%rbp), %eax     ; 

        movl    %eax, -12(%rbp)     ; c = d
        movl    -12(%rbp), %eax     ;

        movl    %eax, -8(%rbp)      ; b = c
        movl    -8(%rbp), %eax      ;

        movl    %eax, -4(%rbp)      ; a = b
        movl    -4(%rbp), %eax      ;

        popq    %rbp

        ret                         ; return %eax, ie. a

gcc ist also eigentlich das ganze Zeug verketten.

  • Ein Compiler kann beliebige Codetransformationen durchführen, die das beobachtbare Verhalten nicht ändern. Daher beweist die Versammlung überhaupt nichts. Das Einzige, worauf Sie sich verlassen können, ist die C++-Standardspezifikation (wenn der Compiler verspricht, den Standard zu befolgen).

    – Markus

    26. Juni 2016 um 11:51 Uhr

Sie können selbst entscheiden, ob diese Art der Codierung gut oder schlecht ist.

  1. Sehen Sie sich einfach den Assembler-Code für die folgenden Zeilen in Ihrer IDE an.

  2. Ändern Sie dann den Code in zwei separate Zuweisungen und sehen Sie sich die Unterschiede an.

Darüber hinaus können Sie auch versuchen, Optimierungen (sowohl Größen- als auch Geschwindigkeitsoptimierungen) in Ihrem Compiler ein- und auszuschalten, um zu sehen, wie sich dies auf den Assemblercode auswirkt.

Benutzer-Avatar
kjelderg

Die Ergebnisse sind die gleichen. Einige Leute ziehen es vor, Zuweisungen zu verketten, wenn sie alle den gleichen Wert haben. An diesem Ansatz ist nichts auszusetzen. Ich persönlich finde das vorzuziehen, wenn die Variablen eng verwandte Bedeutungen haben.

Benutzer-Avatar
Mephist

Wie bereits bemerkt,

sample1 = sample2 = 0;

ist gleich

sample2 = 0;
sample1 = sample2;

Das Problem ist, dass riskant fragte nach eingebettetem c, die häufig verwendet wird, um Register direkt anzusteuern. Viele der Register des Mikrocontrollers haben einen anderen Zweck bei Lese- und Schreibvorgängen. Also im Allgemeinen Es ist nicht das Gleichewie

sample2 = 0;
sample1 = 0;

Sei beispielsweise UDR ein UART-Datenregister. Das Lesen von UDR bedeutet, den empfangenen Wert aus dem Eingangspuffer zu erhalten, während das Schreiben in UDR bedeutet, den gewünschten Wert in den Sendepuffer zu stellen und die Kommunikation herzustellen. In diesem Fall,

sample = UDR = 0;

bedeutet folgendes: a) Wert Null per UART übertragen (UDR = 0;) und b) Eingabepuffer lesen und Daten darin platzieren sample Wert (sample = UDR;).

Sie konnten sehen, dass das Verhalten eingebetteter Systeme viel komplizierter sein könnte, als der Codeschreiber erwarten würde. Verwenden Sie diese Schreibweise beim Programmieren von MCUs sorgfältig.

sample1 = sample2 = 0;

bedeutet

sample1 = 0;
sample2 = 0;  

dann und nur dann, wenn sample2 früher erklärt wird.
So geht das nicht:

int sample1 = sample2 = 0; //sample1 must be declared before assigning 0 to it

1386110cookie-checkMehrfachbelegung in einer Zeile

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

Privacy policy