Forum: Compiler & IDEs bringt einfache Zeigerei einen Performance-Vorteil?


von Micha (Gast)


Lesenswert?

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...

von Joachim D. (Firma: JDCC) (scheppertreiber)


Lesenswert?

In der Praxis ist es das gleiche (obwohl, für Puristen ...).

von Mike (Gast)


Lesenswert?

Joachim Drechsel schrieb:
> In der Praxis ist es das gleiche (obwohl, für Puristen ...).

gefällt mir ;)

von Joachim D. (Firma: JDCC) (scheppertreiber)


Lesenswert?

Mir auch.

Pointer sind das Salz in der Suppe ;)

von Christian B. (casandro)


Lesenswert?

Hängt bestimmt vom Compiler ab, das ist aber eine der wenigen Sachen, 
die ein C Compiler optimieren kann.

von Rolf M. (rmagnus)


Lesenswert?

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.

von Micha (Gast)


Lesenswert?

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 ;)

von Jasch (Gast)


Lesenswert?

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.

von ZeigerGott (Gast)


Lesenswert?

Wer mit Zeigern Arbeitet hat das Tor zur Hölle geöffnet wenn man aber 
weiß was man Macht dann bleibt man aus der Hölle drausen!

von Udo S. (urschmitt)


Lesenswert?

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.

von Adib (Gast)


Lesenswert?

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.

von Ben j. (scarab)


Lesenswert?

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.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

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.

von Jasch (Gast)


Lesenswert?

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. ;-)

von Rolf M. (rmagnus)


Lesenswert?

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.

von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

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

von Klaus W. (mfgkw)


Lesenswert?

bei jedem i!=0 ergibt das true

(solange (i * sizeof(element_type) implizit mit der Größe der 
Feldelemente multipliziert wird)

von Jasch (Gast)


Lesenswert?

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.

von Jasch (Gast)


Lesenswert?

Μα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. ;-)

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

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?

von (prx) A. K. (prx)


Lesenswert?

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.

von Rolf M. (rmagnus)


Lesenswert?

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.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

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.

von Jasch (Gast)


Lesenswert?

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... ;-)

von ET-Tutorials (Gast)


Lesenswert?

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/

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.