lange Zeit bin ich mit C "immer im ersten Gang gefahren". Sprich: ich
hab mich bis zu einem mittelschwer komplexen Projekt durchgemogelt, ohne
dass ich bis dahin das Konzept der Zeiger verstanden hatte.
Habe jetzt einen Code, in dem massenhaft Daten aus Arrays auf die
konventionelle Art gelesen werden, also etwa so:
1
x=array[i];
Bringt es mit dem Gespann GCC / Atmega überhaupt irgend einen Vorteil,
wenn man das so umschreibt?
1
x=*(array+i);
Ich vermute NEIN, wollte aber sicherheitshalber mal fragen...
Micha schrieb:> abe jetzt einen Code, in dem massenhaft Daten aus Arrays auf die> konventionelle Art gelesen werden, also etwa so:> x = array[i];> Bringt es mit dem Gespann GCC / Atmega überhaupt irgend einen Vorteil,> wenn man das so umschreibt?> x = *(array + i);
Das ist exakt das gleiche. Beide Schreibweisen sind zu 100% äquivalent,
und das hat auch nichts damit zu tun, ob's jetzt ein Array oder ein
Zeiger ist, über den du diesen Zugriff machst.
Die zweite Variante ist nicht mehr oder weniger "Zeigerei" als die
erste, aber sie ist schlechter lesbar.
hatte ich vermutet. Die erste Variante ist leichter lesbar. Bei der
zweiten fühle ich mich immer wie der Kandidat der vom Showmaster gefragt
wird:
Nehmen sie jetzt vorne dran ein *, ein &, garnichts, oder den
Telefonjoker ;)
Micha schrieb:> lange Zeit bin ich mit C "immer im ersten Gang gefahren". Sprich: ich> hab mich bis zu einem mittelschwer komplexen Projekt durchgemogelt, ohne> dass ich bis dahin das Konzept der Zeiger verstanden hatte.>> Habe jetzt einen Code, in dem massenhaft Daten aus Arrays auf die> konventionelle Art gelesen werden, also etwa so:>
1
>x=array[i];
2
>
> Bringt es mit dem Gespann GCC / Atmega überhaupt irgend einen Vorteil,> wenn man das so umschreibt?>
1
>x=*(array+i);
2
>
>> Ich vermute NEIN, wollte aber sicherheitshalber mal fragen...
So wie es oben steht eher nicht.
Wenn es was bringen soll muss man den Zeiger inkrementieren, nicht immer
wieder zum Basiszeiger etwas addieren.
Warum?
Das ist der Unterschied:
array + i -> array + sizeof(*array) * i {2 Ops}
array++ -> array + sizeof(*array) {1 Op}
Ob und wie der konkrete Compiler da noch wilde Optimierungen macht oder
sogar die Hardware (Intel z.B. für sizeof(*array) == 2, 4 und so, keine
Ahnung ob ein existierender Compiler das wirklich benutzt) unterstützt -
Glückssache, ausprobieren, Doku lesen.
Ohne Profiler-Daten würde ich da nicht dran herumspielen, lesbarer Code
ist z.B. auch etwas wert.
ZeigerGott schrieb:> Wer mit Zeigern Arbeitet hat das Tor zur Hölle geöffnet
Wohl eher die Windeln hinter sich gelassen
Wichtig werden Zeiger wenn man mit größeren Datenstrukturen umgeht und
die auch an Funktionen übergeben will, bzw duch diesen Aufruf mit einem
Zeiger auf die 'aussen' liegenden Daten die Funktion die Möglichkeit hat
diese Daten zu verändern.
Der 2, noch wichtigere Anwendungsfall ist wenn man dynamische Strukturen
aufbaut (z.B. verkettete Listen) und den Speicher erst zur Laufzeit
anfordert.
Micha schrieb:
...
> x = array[i];
...
> x = *(array + i);>
wie oben bereits angedeutet HAST du das Tor zur Hölle geöffnet.
Frag dich doch mal, was passiert, wenn:
1) ein Element nicht nur ein Byte gross ist
*(array + i); hab ich das i-te Element oder das i-te byte ab Addresse?
2) aus Optimierungsgründen zwischen zwei Elementen noch etwas Leerraum
(padding) gelassen wird. (damit Elemente immer an geraden Addressen
anfangen)
&array[i] != array + (i * sizeof(element_type))
In beiden Fällen kannst du auch mal was ganz anderes als Addresse
errechnen.
Manche Programmierspachen verbieten gerade diese Art der
Pointer-Arithmetik.
Du solltest schon ganz genau wissen, was du tust.
Grüße, der Adib.
Adib schrieb:> 2) aus Optimierungsgründen zwischen zwei Elementen noch etwas Leerraum> (padding) gelassen wird. (damit Elemente immer an geraden Addressen> anfangen)> &array[i] != array + (i * sizeof(element_type))>> In beiden Fällen kannst du auch mal was ganz anderes als Addresse> errechnen.
Er Programmiert doch kein Assembler, ein C Compiler MUSS mit solcher
Zeiger-Arithmetik umgehen können, ansonsten taugt er nichts.
Adib schrieb:> Micha schrieb:> ...>> x = array[i];> ...>> x = *(array + i);>>> wie oben bereits angedeutet HAST du das Tor zur Hölle geöffnet.>> Frag dich doch mal, was passiert, wenn:> 1) ein Element nicht nur ein Byte gross ist> *(array + i); hab ich das i-te Element oder das i-te byte ab Addresse?>> 2) aus Optimierungsgründen zwischen zwei Elementen noch etwas Leerraum> (padding) gelassen wird. (damit Elemente immer an geraden Addressen> anfangen)> &array[i] != array + (i * sizeof(element_type))
Und was hat das mit obigen Formulierungen zu tun?
Im bytes gerechnet, bedeutet "array + i" nicht anderes als "array +
i*sizeof(*array)".
Die Semantik von array[i] und *(array+i) ist immer noch die selbe.
Adib schrieb:> Micha schrieb:> ...>> x = array[i];> ...>> x = *(array + i);>>> wie oben bereits angedeutet HAST du das Tor zur Hölle geöffnet.>> Frag dich doch mal, was passiert, wenn:> 1) ein Element nicht nur ein Byte gross ist> *(array + i); hab ich das i-te Element oder das i-te byte ab Addresse?
Das i-te Element, per Definition.
> 2) aus Optimierungsgründen zwischen zwei Elementen noch etwas Leerraum> (padding) gelassen wird. (damit Elemente immer an geraden Addressen> anfangen)> &array[i] != array + (i * sizeof(element_type))
Das ergibt niemals true, echt nicht.
> In beiden Fällen kannst du auch mal was ganz anderes als Addresse> errechnen.
Nein.
Das ist alles im C-Standard genau beschrieben. Wenn man natürlich keinen
C-Compiler sondern ein, hmm, etwas nur ähnliches hat, dann hat man
sowieso verloren. Willkommen in der Hölle. ;-)
Adib schrieb:> 2) aus Optimierungsgründen zwischen zwei Elementen noch etwas Leerraum> (padding) gelassen wird.
Das ist in C verboten.
> Manche Programmierspachen verbieten gerade diese Art der> Pointer-Arithmetik.
C gehört nicht zu diesen.
Jasch schrieb:>> 2) aus Optimierungsgründen zwischen zwei Elementen noch etwas Leerraum>> (padding) gelassen wird. (damit Elemente immer an geraden Addressen>> anfangen)>> &array[i] != array + (i * sizeof(element_type))>> Das ergibt niemals true, echt nicht.
Och, bei genügend großem sizeof(element_type) * i könnte das schon einen
passenden Überlauf....
SCNR
Matthias
Klaus Wachtler schrieb:> bei jedem i!=0 ergibt das true>> (solange (i * sizeof(element_type) implizit mit der Größe der> Feldelemente multipliziert wird)
Aarrrggghhhhhh!
Ja, Du hast recht. Autsch, nicht genau hingesehen.
Μαtthias W. schrieb:> Jasch schrieb:>>> 2) aus Optimierungsgründen zwischen zwei Elementen noch etwas Leerraum>>> (padding) gelassen wird. (damit Elemente immer an geraden Addressen>>> anfangen)>>> &array[i] != array + (i * sizeof(element_type))>>>> Das ergibt niemals true, echt nicht.>> Och, bei genügend großem sizeof(element_type) * i könnte das schon einen> passenden Überlauf....
Abgesehen von dem von Klaus gezeigten Fehler darin, also angenommen da
stünde &array[i] != array + i, dann wären ja sowohl rechte als auch
linke Seite kaputt, also durch Pointer-Arithmetik nichts verloren.
Wenn man dann noch sieht dass einem C99 (und wohl auch C11 oder wie das
heisst) ja nur ein Objekt von 64K-1 Bytes Größe zusichert, hmm, auf den
heutigen Rechnern...
> *SCNR*
SCNR either. ;-)
Jasch schrieb:> Wenn man dann noch sieht dass einem C99 (und wohl auch C11 oder wie das> heisst) ja nur ein Objekt von 64K-1 Bytes Größe zusichert, hmm, auf den> heutigen Rechnern...
Wo steht denn sowas?
Möglicherweise meint er die Konsequenz aus der Zeigerarithmetik, die nur
Arrays bis zur Grösse von 32767 Bytes garantiert, weil "int" nur mit
mindestens 16 Bits definiert ist.
Jasch schrieb:> Wenn man dann noch sieht dass einem C99 (und wohl auch C11 oder wie das> heisst) ja nur ein Objekt von 64K-1 Bytes Größe zusichert, hmm, auf den> heutigen Rechnern...
Anders formuliert: Es fordert von den Compilern, daß sie mindestens
soviel unterstützen.
Johann L. schrieb:> Wo steht denn sowas?
In C99 im Kapitel 5.2.4.1 "Translation limits":
The implementation shall be able to translate and execute at least one
program that contains at least one instance of every one of the
following limits:
[...]
— 65535 bytes in an object (in a hosted environment only)
Da sind noch ein Haufen andere lustige Limits drin, wie z.B. die
maximale Tiefe von #includes, maximale Zahl von Funktionsparametern
u.s.w.
Rolf Magnus schrieb:> Jasch schrieb:>> Wenn man dann noch sieht dass einem C99 (und wohl auch C11 oder wie das>> heisst) ja nur ein Objekt von 64K-1 Bytes Größe zusichert, hmm, auf den>> heutigen Rechnern...>> Anders formuliert: Es fordert von den Compilern, daß sie mindestens> soviel unterstützen.>> Johann L. schrieb:>> Wo steht denn sowas?>> In C99 im Kapitel 5.2.4.1 "Translation limits":>> The implementation shall be able to translate and execute at least one> program that contains at least one instance of every one of the> following limits:>> [...]>> — 65535 bytes in an object (in a hosted environment only)
Dabei geht's um Einschränkungen, die durch das Host-System zustande
kommen, also das System, welches das Programm übersetzt.
Die Klausel sagt, daß das Host-System bestimmte Mingestanforderungen
mitbringen muss, um eine sinnvolle Implementation bieten zu können.
Johann L. schrieb:> Rolf Magnus schrieb:>> Jasch schrieb:>>> Wenn man dann noch sieht dass einem C99 (und wohl auch C11 oder wie das>>> heisst) ja nur ein Objekt von 64K-1 Bytes Größe zusichert, hmm, auf den>>> heutigen Rechnern...>>>> Anders formuliert: Es fordert von den Compilern, daß sie mindestens>> soviel unterstützen.>>>> Johann L. schrieb:>>> Wo steht denn sowas?>>>> In C99 im Kapitel 5.2.4.1 "Translation limits":>>>> The implementation shall be able to translate and execute at least one>> program that contains at least one instance of every one of the>> following limits:>>>> [...]>>>> — 65535 bytes in an object (in a hosted environment only)>> Dabei geht's um Einschränkungen, die durch das Host-System zustande> kommen, also das System, welches das Programm übersetzt.>> Die Klausel sagt, daß das Host-System bestimmte Mingestanforderungen> mitbringen muss, um eine sinnvolle Implementation bieten zu können.
Da steht "translate and execute", nix nur Übersetzung. Hosted
environment ist gemeint als Gegensatz zu "freestanding implementation" -
was dann "embedded systems" wie AVR, ARM usw. meint, oder auch
Kernelprogrammierung, alles ohne "richtiges" Betriebssystem.
Wie genau das jetzt zu interpretieren ist wenn die Übersetzungsumgebung
"hosted", die Ausführungsumgebung "freestanding" ist - uuhhh, language
lawyer fragen.
Hehehe, alleine schon das "translate and execute at least one program"
ist sowas von Oberklasse... ;-)
Wem das alles hier zu kompliziert wird ;-) ,
kanj ja mal in meine Grundlagen-VIDEOS zum Thema Pointer reingucken.
Ab Folge 36
http://et-tutorials.de/mikrocontroller/