Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
| Beide Seiten der vorigen Revision Vorhergehende Überarbeitung Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
|
c:tutorial:attribute [2015/02/22 22:35] dani93 |
c:tutorial:attribute [2022/09/22 19:58] (aktuell) |
||
|---|---|---|---|
| Zeile 1: | Zeile 1: | ||
| ====== Attribute ====== | ====== Attribute ====== | ||
| - | |||
| - | * Was sind Attribute? | ||
| - | * unsigned | ||
| - | * const | ||
| - | * Konstanten | ||
| - | * Read-Only-Speicherbereiche | ||
| - | * Zeigerkonstanten | ||
| - | * Scopes | ||
| - | * static | ||
| - | * volatile | ||
| ===== Was sind Attribute? ===== | ===== Was sind Attribute? ===== | ||
| Zeile 15: | Zeile 5: | ||
| Von einem Attribut spricht man, wenn man einen Gegenstand genauer beschreibt. Der rote Ball ist ein Ball, der - wenn man ihn genauer beschreibt - als rot beschrieben wird. Rot ist das Attribut. Wir werden uns hier Datentypen-Attribute ansehen, die die Sprache C kennt. Das bedeutet, dass man der Beschreibung eines Datentyps noch eine genauere Beschreibung hinzufügen kann. | Von einem Attribut spricht man, wenn man einen Gegenstand genauer beschreibt. Der rote Ball ist ein Ball, der - wenn man ihn genauer beschreibt - als rot beschrieben wird. Rot ist das Attribut. Wir werden uns hier Datentypen-Attribute ansehen, die die Sprache C kennt. Das bedeutet, dass man der Beschreibung eines Datentyps noch eine genauere Beschreibung hinzufügen kann. | ||
| - | ===== Das Attribut unsigned ===== | + | ===== unsigned ===== |
| - | Integer-Datentypen zählen von einem maximalen negativen Wert zu einem maximalen positiven Wert. So zählt ein [[c:type:char]] von -128 bis 127. Einen einzelnen Farbwert (rot, grün oder blau) beschreibt man allerdings in Form seiner Intensität, von keine Intensität (0) bis maximale Intensität (255). Um die maximale Intensität zu speichern, müssen wir uns die Zahl 255 merken und die passt nicht in ein [[c:type:char]]. Integerdatentypen sind per Voreinstellung immer ''signed''. ''signed'' ist übrigens auch ein Schlüsselwort der Sprache C, aber es benutzt eigentlich keiner, weil es die Voreinstellung ist. | + | Integer-Datentypen zählen von einem maximalen negativen Wert zu einem maximalen positiven Wert. So zählt ein [[c:type:char]] von -128 bis 127. Einen einzelnen Farbwert (rot, grün oder blau) beschreibt man allerdings in Form seiner Intensität: Von keine Intensität (0) bis maximale Intensität (255). Um die maximale Intensität zu speichern, müssen wir uns die Zahl 255 merken und die passt nicht in ein [[c:type:char]]. Integerdatentypen sind per Voreinstellung immer ''signed''. ''signed'' ist übrigens auch ein Schlüsselwort der Sprache C, aber es benutzt eigentlich keiner, weil es die Voreinstellung ist. |
| Wenn wir bei einem ''signed char'' also die ungebrauchten negativen Zahlen den positiven Zahlen hinzufügen könnten, dann hätten wir 127 (maximaler positiver Wert) + 128 (maximaler negativer Wert) = 255 als größte Zahl - mit der 0 also zusammen 256 unterschiedliche Werte, die wir mit einem ''unsigned char'' ausdrücken können. | Wenn wir bei einem ''signed char'' also die ungebrauchten negativen Zahlen den positiven Zahlen hinzufügen könnten, dann hätten wir 127 (maximaler positiver Wert) + 128 (maximaler negativer Wert) = 255 als größte Zahl - mit der 0 also zusammen 256 unterschiedliche Werte, die wir mit einem ''unsigned char'' ausdrücken können. | ||
| Zeile 41: | Zeile 31: | ||
| | | | | unsigned | 0 | (18.446.744.073.709.551.615) | | | | | | unsigned | 0 | (18.446.744.073.709.551.615) | | ||
| \\ | \\ | ||
| - | Die angegebenen Größen sind Mindestgrößen! Die wirklichen Größen finden sich in der Headerdatei ''[[c:lib:limits:|limit.h]]''. Gerade für den Datentyp ''[[c:type:int]]'' gilt heute eher, dass er 32 Bit breit ist und damit ''[[c:type:long]]'' entspricht. Aber C garantiert das für ''[[c:type:int]]'' nicht, sondern nur 16 Bit, wie bei ''[[c:type:short]]''. | + | Die angegebenen Größen sind Mindestgrößen! Die wirklichen Größen finden sich in der Headerdatei ''[[c:lib:limits:|limits.h]]''. Gerade für den Datentyp ''[[c:type:int]]'' gilt heute eher, dass er 32 Bit breit ist und damit ''[[c:type:long]]'' entspricht. Aber C garantiert das für ''[[c:type:int]]'' nicht, sondern nur 16 Bit, wie bei ''[[c:type:short]]''. |
| - | Auch wenn sich ''int'' kürzer schreibt als ''unsigned int'', so steckt für den Compiler, wie auch für den Menschen eine zusätzliche Information in diesem Datentyp. Auf ein Array darf man meistens nur mit positiven Werten zugreifen. Möchte man auf ein Array mit 256 Elementen zugreifen, so darf der Index selbst kein char sein, sondern muss mindestens ein ''unsigned char'' sein, da man ansonsten nicht hinter den Beginn des Arrays zugreift, sondern von 128 Elementen vor dem Arraybeginn bis 127 Elemente nach dem Arraybeginn. Die hinteren 128 Elemente erreicht man so nicht, während man gleichzeitig 128 Elemente erreicht, auf die man nicht zugreifen darf. Dies zu vergessen ist ein beliebter Anfängerfehler. Es ist auch nicht in der Verantwortung der Programmiersprache, dem Entwickler zu erklären, was er tun und lassen darf, sondern Du musst dem Computer erklären, was er tun soll. | + | Auch wenn sich ''int'' kürzer schreibt als ''unsigned int'', so steckt für den Compiler, wie auch für den Menschen, eine zusätzliche Information in diesem Datentyp. Auf ein Array darf man meistens nur mit positiven Werten zugreifen. Möchte man auf ein Array mit 256 Elementen zugreifen, so darf der Index selbst kein ''char'' sein, weil dieser Typ wie bereits erwähnt nur einen Wertebereich von -128 bis 127 abdeckt. Obwohl das 256 verschiedene Werte sind, können die höheren 128 der 256 Elemente im Array nicht erreicht werden. Gleichzeitig erreicht man über den negativen Wertebereich 128 Elemente, auf die man eigentlich nicht zugreifen darf. Der Index muss daher mindestens ein ''unsigned char'' mit einem Wertebereich von 0 bis 255 sein, um auf alle 256 gültigen Elemente des Arrays zuzugreifen. Dies zu vergessen ist ein beliebter Anfängerfehler. Es ist auch nicht in der Verantwortung der Programmiersprache, dem Entwickler zu erklären, was er tun und lassen darf, sondern Du musst dem Computer erklären, was er tun soll. |
| - | Bei einem Array, bei dem Du hinter den Start zugreifen möchtest, benutze also möglichst Variablen eines Integertyps, der mit dem Attribut ''unsigned'' erweitert wurde. | + | Bei einem Array, bei dem Du nur positive Indizes verwenden möchtest, benutze also möglichst Variablen eines Integertyps, der mit dem Attribut ''unsigned'' erweitert wurde. |
| Schauen wir uns das an: | Schauen wir uns das an: | ||
| Zeile 55: | Zeile 45: | ||
| </code> | </code> | ||
| - | Verwendest Du für ''index'' eine unsigned-int-Variable kann Dir dies nicht passieren. | + | Verwendest Du für ''index'' eine Variable vom Typ ''unsigned int'', kann Dir dies nicht passieren. |
| Dies solltest Du grundsätzlich tun, wenn Werte nicht negativ werden können. Nehmen wir die Anzahl Daten, zum Beispiel die Größe von Arbeitsspeicher. Man kann keine negative Menge Speicher anfordern: ''unsigned'' verwenden! | Dies solltest Du grundsätzlich tun, wenn Werte nicht negativ werden können. Nehmen wir die Anzahl Daten, zum Beispiel die Größe von Arbeitsspeicher. Man kann keine negative Menge Speicher anfordern: ''unsigned'' verwenden! | ||
| Nehmen wir die Länge eines Strings: Ein String kann nicht kürzer als 0 Zeichen lang sein: ''unsigned'' verwenden! | Nehmen wir die Länge eines Strings: Ein String kann nicht kürzer als 0 Zeichen lang sein: ''unsigned'' verwenden! | ||
| - | Die bessere Version unserer strLength()-Routine sieht also so aus: | + | Die bessere Version unserer ''strLength()''-Routine sieht also so aus: |
| <code cpp> | <code cpp> | ||
| unsigned int strLength( char * string ) | unsigned int strLength( char * string ) | ||
| Zeile 78: | Zeile 68: | ||
| ===== const ===== | ===== const ===== | ||
| - | Const und [[cpp:const:start|in C++ "Const-Correctness"]] sind sehr wichtige Themen, um die Qualität von Software zu erhöhen. Wie unsigned ist const eine zusätzliche Garantie, die man vergibt. Die Garantie bei const lautet, dass sich der Wert nicht verändern wird und das ist eine sehr wichtige Eigenschaft. | + | ''const'' und [[cpp:const:start|in C++ "Const-Correctness"]] sind sehr wichtige Themen, um die Qualität von Software zu erhöhen. Wie ''unsigned'' ist ''const'' eine zusätzliche Garantie, die man vergibt. Die Garantie bei ''const'' lautet, dass sich der Wert nicht verändern wird und das ist eine sehr wichtige Eigenschaft. |
| ==== Konstanten ==== | ==== Konstanten ==== | ||
| Zeile 131: | Zeile 121: | ||
| const.c:12: error: assignment of read-only variable ‘pi’</code> | const.c:12: error: assignment of read-only variable ‘pi’</code> | ||
| - | Da der Compiler nun versteht, dass er pi nicht überschreiben darf, kann er diesen Fehler auch erkennen. | + | Da der Compiler nun versteht, dass er ''pi'' nicht überschreiben darf, kann er diesen Fehler auch erkennen. |
| Wir korrigieren die Methode ''circumference'': | Wir korrigieren die Methode ''circumference'': | ||
| Zeile 165: | Zeile 155: | ||
| </code> | </code> | ||
| - | Aber folgendes funktioniert ist gefährlich: | + | Aber folgendes funktioniert und ist gefährlich: |
| <code cpp> | <code cpp> | ||
| #include <stdio.h> | #include <stdio.h> | ||
| Zeile 175: | Zeile 165: | ||
| return 0; | return 0; | ||
| }</code> | }</code> | ||
| + | |||
| Der gcc (Version 4.9.1) akzeptiert das, aber das Verhalten wird sich ändern. Früher hat man die Fehlererkennung durch den Compiler nicht so ernst genommen und so entstand viel Quelltext, der solche Text-Zuweisungen enthält. Damit diese weiterhin kompilieren und nicht urplötzlich tausende Zeilen geändert werden müssen, akzeptiert der gcc derartiges. | Der gcc (Version 4.9.1) akzeptiert das, aber das Verhalten wird sich ändern. Früher hat man die Fehlererkennung durch den Compiler nicht so ernst genommen und so entstand viel Quelltext, der solche Text-Zuweisungen enthält. Damit diese weiterhin kompilieren und nicht urplötzlich tausende Zeilen geändert werden müssen, akzeptiert der gcc derartiges. | ||
| - | In C++ ist const mächtiger und damit auch weiter verbreitet: der g++ meckert schonmal: | + | In C++ ist ''const'' mächtiger und damit auch weiter verbreitet: der g++ meckert schonmal: |
| - | <code>constptr.c:5: warning: initialization discards qualifiers from pointer target type</code> | + | <code>constptr.c:5:21: warning: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]</code> |
| Was passiert da eigentlich? Der Text "proggen.org" ist im ausführbaren Programm gespeichert. Die Variable ''arrayVariable'' ist eine Variable, deren Größe entsprechend der Länge des Textes "proggen.org" gewählt wird. Und dann wird der Text "proggen.org" in die Variable kopiert. In unserem Array dürfen wir dann den Text nach belieben ändern. Den Text "proggen.org" dürfen wir aber nicht ändern, denn sonst würde bei jedem Aufruf von "function" die Variable ''arrayVariable'' verändert sein. | Was passiert da eigentlich? Der Text "proggen.org" ist im ausführbaren Programm gespeichert. Die Variable ''arrayVariable'' ist eine Variable, deren Größe entsprechend der Länge des Textes "proggen.org" gewählt wird. Und dann wird der Text "proggen.org" in die Variable kopiert. In unserem Array dürfen wir dann den Text nach belieben ändern. Den Text "proggen.org" dürfen wir aber nicht ändern, denn sonst würde bei jedem Aufruf von "function" die Variable ''arrayVariable'' verändert sein. | ||
| Zeile 193: | Zeile 184: | ||
| return 0; | return 0; | ||
| }</code> | }</code> | ||
| - | kompilieren das und führen es aus: | + | |
| + | Wir kompilieren das und führen es aus: | ||
| <code>$ ./a.out | <code>$ ./a.out | ||
| Speicherzugriffsfehler | Speicherzugriffsfehler | ||
| </code> | </code> | ||
| - | Ein String, der in Anführungszeichen steht ist eine Zeiger auf konstante Buchstaben: char const *. | + | Ein String, der in Anführungszeichen steht ist eine Zeiger auf konstante Buchstaben: ''char const *'' |
| Der korrekte Quelltext sieht also so aus: | Der korrekte Quelltext sieht also so aus: | ||
| <code cpp> | <code cpp> | ||
| Zeile 221: | Zeile 214: | ||
| Interessant ist das nun, wenn Zeiger an Funktionen übergeben werden und man sicher sein möchte, dass die Daten von diesen Funktionen nicht verändert werden - zum Beispiel, weil die Daten nicht verändert werden dürfen. | Interessant ist das nun, wenn Zeiger an Funktionen übergeben werden und man sicher sein möchte, dass die Daten von diesen Funktionen nicht verändert werden - zum Beispiel, weil die Daten nicht verändert werden dürfen. | ||
| - | Schauen wir uns eine Funktion wie strLength nocheinmal an, die keine Daten ändert und eine weitere Funktion, die den übergebenen String mit Punkten überschreibt: | + | Schauen wir uns eine Funktion wie ''strLength'' nochmals an, die keine Daten ändert und eine weitere Funktion, die den übergebenen String mit Punkten überschreibt: |
| <code cpp> | <code cpp> | ||
| #include <stdio.h> | #include <stdio.h> | ||
| Zeile 265: | Zeile 258: | ||
| </code> | </code> | ||
| - | Die Funktion strLength() funktioniert, da wir glücklicherweise nichts ändern. Anschließend wird ausgegeben, wie lang der Text ist und das Programm stürzt in der Funktion ''dots()'' ab und stellt klar, dass wir mit konstanten Strings arbeiten. Beide Funktionen bekommen nun statt ''char *'' einen ''char const *'' übergeben: | + | Die Funktion ''strLength()'' funktioniert, da wir glücklicherweise nichts ändern. Anschließend wird ausgegeben, wie lang der Text ist und das Programm stürzt in der Funktion ''dots()'' ab und stellt klar, dass wir mit konstanten Strings arbeiten. Beide Funktionen bekommen nun statt ''char *'' einen ''char const *'' übergeben: |
| <code cpp> | <code cpp> | ||
| Zeile 335: | Zeile 328: | ||
| int main( void ) | int main( void ) | ||
| { | { | ||
| - | char const array[] = "proggen.org"; | + | char array[] = "proggen.org"; |
| unsigned int length = strLength( array ); | unsigned int length = strLength( array ); | ||
| Zeile 366: | Zeile 359: | ||
| <code cpp>char const * ptr = "proggen.org";</code> | <code cpp>char const * ptr = "proggen.org";</code> | ||
| - | Das ist in seiner Bedeutung gleichwertig, es macht also für das Programm keinen Unterschied. Ich empfehle trotzdem const nach dem Datentyp zu schreiben, um Verwechslungen auszuschließen. Schauen wir uns folgende Zeigervariablen an: | + | Das ist in seiner Bedeutung gleichwertig, es macht also für den Compiler keinen Unterschied. Ich empfehle trotzdem ''const'' nach dem Datentyp zu schreiben, um Verwechslungen auszuschließen. Schauen wir uns folgende Zeigervariablen an: |
| <code cpp> | <code cpp> | ||
| char const * ptr; | char const * ptr; | ||
| Zeile 373: | Zeile 366: | ||
| ptr = "Hallo Welt"; | ptr = "Hallo Welt"; | ||
| </code> | </code> | ||
| + | |||
| Wir können hier den Wert der Zeigervariablen änderen, mal zeigt sie auf das eine Array mit konstanten chars, mal auf ein anderes Array mit konstanten chars. Man kann aber auch Zeigerkonstanten definieren, die man - wie alle anderen Konstanten - sofort mit einem Wert initialisieren, also beschreiben, muss. | Wir können hier den Wert der Zeigervariablen änderen, mal zeigt sie auf das eine Array mit konstanten chars, mal auf ein anderes Array mit konstanten chars. Man kann aber auch Zeigerkonstanten definieren, die man - wie alle anderen Konstanten - sofort mit einem Wert initialisieren, also beschreiben, muss. | ||
| Zeile 387: | Zeile 381: | ||
| denn hier ist der Datentyp nun doppelt konstant und der Zeiger bleibt variabel. | denn hier ist der Datentyp nun doppelt konstant und der Zeiger bleibt variabel. | ||
| - | Eine Zeigerkonstante muss nicht zwangsläufig auf konstante Daten zeigen: die Konstante kann auch durchaus auf variable Daten zeigen: | + | Eine Zeigerkonstante muss nicht zwangsläufig auf konstante Daten zeigen: Die Konstante kann auch durchaus auf variable Daten zeigen: |
| <code cpp> | <code cpp> | ||
| char array[] = "Hallo proggen.org"; | char array[] = "Hallo proggen.org"; | ||
| Zeile 398: | Zeile 392: | ||
| Dies gilt auch in Hinblick zu C++, wo es konstante Methoden gibt. Würde man hier ''const'' vor die Signatur schreiben, sähe das so aus: | Dies gilt auch in Hinblick zu C++, wo es konstante Methoden gibt. Würde man hier ''const'' vor die Signatur schreiben, sähe das so aus: | ||
| <code cpp>const char * method()</code> | <code cpp>const char * method()</code> | ||
| - | Das geht nicht - das besagt, dass ein Zeiger auf konstante Chars zurückgegeben wird. Auch hier wird ''const'' hinter die betreffende Methode geschrieben: | + | Das geht nicht - das besagt, dass ein Zeiger auf konstante Zeichen zurückgegeben wird. Auch hier wird ''const'' hinter die betreffende Methode geschrieben: |
| <code cpp>char * method() const</code> | <code cpp>char * method() const</code> | ||
| Zeile 465: | Zeile 459: | ||
| Man kann immer auf die Variablen im eigenen Scope und den darüber angeordneten Scopes zugreifen. Globale Variablen liegen über allen Scopes. | Man kann immer auf die Variablen im eigenen Scope und den darüber angeordneten Scopes zugreifen. Globale Variablen liegen über allen Scopes. | ||
| - | Scopes beschränken also die Lebensdauer von Variablen, globale Variablen liegen gewissermaßen in einem übergeordneten Scope, der erst zerstört wird, nachdem die Funktion main() verlassen wurde. Es gibt ein Leben nach main() - und genauso eins davor, zum Beispiel, um die Variablen anzulegen. Unser Programm arbeitet also bereits, bevor main() gerufen wird. main() wird erst gestartet, nachdem das globale Scope eingerichtet wurde und alle anderen erforderlichen Vorbereitungen durchgeführt sind. | + | Scopes beschränken also die Lebensdauer von Variablen, globale Variablen liegen gewissermaßen in einem übergeordneten Scope, der erst zerstört wird, nachdem die Funktion ''main()'' verlassen wurde. Es gibt ein Leben nach ''main()'' - und genauso eins davor, zum Beispiel, um die Variablen anzulegen. Unser Programm arbeitet also bereits, bevor ''main()'' gerufen wird. ''main()'' wird erst gestartet, nachdem das globale Scope eingerichtet wurde und alle anderen erforderlichen Vorbereitungen durchgeführt sind. |
| ===== static ===== | ===== static ===== | ||
| - | Das Attribut static bewirkt, dass eine beschriebene Variable eine statische Adresse erhält, die sich nicht ändert. Das bedeutet zum einen, dass es sich um genau eine Variable handelt - klar, sagst Du, wieviele auch sonst? | + | Das Attribut ''static'' bewirkt, dass eine beschriebene Variable eine statische Adresse erhält, die sich nicht ändert. Das bedeutet zum einen, dass es sich um genau eine Variable handelt - klar, sagst Du, wieviele auch sonst? |
| - | Nun wir haben gerade gelesen, dass es Scopes gibt und wann immer eine Funktion gerufen wird, Variablen erzeugt und am Schluss wieder vernichtet werden. Das ist aber nicht immer gewünscht. Stellen wir uns eine Funktion count() vor, die zählt, wie oft sie aufgerufen wurde: | + | Nun wir haben gerade gelesen, dass es Scopes gibt und wann immer eine Funktion gerufen wird, Variablen erzeugt und am Schluss wieder vernichtet werden. Das ist aber nicht immer gewünscht. Stellen wir uns eine Funktion ''count()'' vor, die zählt, wie oft sie aufgerufen wurde: |
| <code cpp> | <code cpp> | ||
| Zeile 484: | Zeile 478: | ||
| </code> | </code> | ||
| - | Die Variable counter wird jedesmal neu angelegt, mit 0 initialisiert und anschließend um 1 hochgezählt. Die Funktion gibt also grundsätzlich 1 zurück. So war das nicht gedacht. Wir brauchen also eine Variable, die am Ende des Funktionsaufrufs nicht einfach verschwindet. Wir wissen, dass der globale Scope erst nach dem Verlassen von main() zerstört wird, der Wert der Variablen also erhalten bleibt: | + | Die Variable ''counter'' wird jedesmal neu angelegt, mit 0 initialisiert und anschließend um 1 hochgezählt. Die Funktion gibt also grundsätzlich 1 zurück. So war das nicht gedacht. Wir brauchen also eine Variable, die am Ende des Funktionsaufrufs nicht einfach verschwindet. Wir wissen, dass der globale Scope erst nach dem Verlassen von main() zerstört wird, der Wert der Variablen also erhalten bleibt: |
| <code cpp> | <code cpp> | ||
| Zeile 498: | Zeile 492: | ||
| So funktioniert es! | So funktioniert es! | ||
| - | Aber dennoch ist die Lösung eher unschön, denn jeder kann die Variable counter verändern - wir wollen ein Problem lösen, müssen aber zwei Identifier, nämlich count und counter, in den globalen Namensraum setzen. Vermutlich kommt es schnell zu Verwechslungen, ob die Funktion nun count() oder counter() heißt. Es wäre also schön, wenn die Variable ''counter'' außerhalb der Funktion ''count()'' nicht sichtbar wäre. | + | Aber dennoch ist die Lösung eher unschön, denn jeder kann die Variable ''counter'' verändern - wir wollen ein Problem lösen, müssen aber zwei Identifier, nämlich ''count'' und ''counter'', in den globalen Namensraum setzen. Vermutlich kommt es schnell zu Verwechslungen, ob die Funktion nun ''count()'' oder ''counter()'' heißt. Es wäre also schön, wenn die Variable ''counter'' außerhalb der Funktion ''count()'' nicht sichtbar wäre. |
| Und hier kommt ''static'' das erste Mal ins Spiel. Alle globalen Variablen sind statisch, also einmalig an einer festen Adresse. | Und hier kommt ''static'' das erste Mal ins Spiel. Alle globalen Variablen sind statisch, also einmalig an einer festen Adresse. | ||
| Zeile 532: | Zeile 526: | ||
| ===== volatile ===== | ===== volatile ===== | ||
| - | ''volatile'' bedeutet soviel wie 'flüchtig' oder 'sprunghaft'. C wird gerne in der hardwarenahen Programmierung verwendet und wenn auf einen Speicherbereich mehrere Prozessoren schreibend zugreifen können, so darf man nicht davon ausgehen, dass diese Speicherbereiche unverändert bleiben, wenn man selbst keine Änderung daran vornimmt. | + | ''volatile'' bedeutet soviel wie 'flüchtig' oder 'sprunghaft'. C wird gerne in der hardwarenahen Programmierung verwendet und wenn auf einen Speicherbereich mehrere Prozessoren schreibend zugreifen können, so darf man nicht davon ausgehen, dass diese Speicherbereiche unverändert bleiben, auch wenn man selbst keine Änderung daran vornimmt. |
| Prozessoren können viel schneller rechnen, wenn sie Variablen in den Prozessorkern laden und dann damit arbeiten. Das wissen die Compilerhersteller und so wird bei Schleifen wie | Prozessoren können viel schneller rechnen, wenn sie Variablen in den Prozessorkern laden und dann damit arbeiten. Das wissen die Compilerhersteller und so wird bei Schleifen wie | ||