mikrocontroller.net

Forum: Compiler & IDEs Frage zur Durchlaufzeit und Speicher von 15 If-Schleife


Autor: Stephan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Morgen,

ich hab mal wieder eine Frage.
Wenn ich mit einer oder mehreren If-Schleife/n 15 Variablen abfragen 
möchte, es kann immer nur eine Abfrage von 15 wahr sein, kann ich ja 
eine If-Schleife schreiben in der alle 15 Variablen mit ODER Verknüpft 
sind und ich kann 15 einzelne Schleifen schreiben in der jeweils nur 
eine Variable abgefragt wird. Ich schreibe die ganze Geschichte in C.
Ich hab mir im Eclipse mal das Disassembly anzeigen lassen und komm auf 
einen unterschied von 26 Befehlen, da aber nur eine Abfrage wahr werden 
kann weiß ich nicht ob ich beim Programmdurchlauf eine Zeit ersparniss 
habe.
Meine Frage an euch ist nun, verändert sich die Durchlaufzeit und 
Speicherbedarf der main-Funktion (siehe unten) von Bsp1 zu Bsp2?

Ich dank euch mal wieder für eure Hilfe.
Gruß
Stephan

Bsp1:
#include <stdlib.h>

int main (void)
{
  int variable[15];
  char test;

  while(1)
  {
    if(variable[0] == 0 || variable[1] == 0 || ... || variable[13] == 0 || variable[14] == 0)
    {
      test = "BlaBlaBla";
    }

    
  }
}


Bsp2:
#include <stdlib.h>

int main (void)
{
  int variable[15];
  char test;

  while(1)
  {
    if(variable[0] == 0)
    {
      test = "BlaBlaBLa";
    }

    if(variable[1] == 0)
    {
      test = "BlaBlaBLa";
    }

    .
    .
    .

     if(variable[13] == 0)
    {
      test = "BlaBlaBLa";
    }

    if(variable[14] == 0)
    {
      test = "BlaBlaBLa";
    }
  }
}


Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stephan schrieb:
> da aber nur eine Abfrage wahr werden
> kann

Nö, es können alle 16 wahr sein, Du fragst ja 16 Variablen ab.

Das logische OR bricht nur nach der ersten ab, die wahr ist.


Peter

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stephan schrieb:

Eine Schleife heisst Schleife, weil dort etwas wiederholt wird. Bei 
einem if wird nichts wiederholt, dort wird eine Auswahl getroffen. Darum 
ist ein if keine Schleife, sondern eine Abfrage oder Auswahl.


> möchte, es kann immer nur eine Abfrage von 15 wahr sein, kann ich ja
> eine If-Schleife schreiben in der alle 15 Variablen mit ODER Verknüpft
> sind und ich kann 15 einzelne Schleifen schreiben in der jeweils nur
> eine Variable abgefragt wird. Ich schreibe die ganze Geschichte in C.
> Ich hab mir im Eclipse mal das Disassembly anzeigen lassen und komm auf
> einen unterschied von 26 Befehlen,

logisch.
Kein Mensch sagt, dass in allen 15 Einzel-Abfragen identischer Code 
stehen muss. Und ich denke da erwartest du etwas zuviel vom Optimizer, 
wenn er das rausfinden und zusammenführen soll.

> Meine Frage an euch ist nun, verändert sich die Durchlaufzeit und
> Speicherbedarf der main-Funktion (siehe unten) von Bsp1 zu Bsp2?

Da gibt es nur 1 Möglichkeit: ausprobieren und nachsehen, was der 
Compiler daraus macht.
Die Erwarteungshaltung müsste aber sein: Die ODER Lösung ist schneller. 
Schon alleine aus dem Grund, weil bei ODER eine Short-Cut Evalutation 
gemacht werden muss. Sprich: Ist die erste Bedingung wahr, werden die 
anderen Bedingungen gar nicht mehr ausgewertet. Bei deiner if-Lösung 
hingegen, kann es je nach tatsächlichem Variableninhalt auch dazu 
kommen, dass der Codeteil doppelt, dreifach etc. ausgeführt wird :-) In 
diesem Sinne gleichwertig zum ODER wäre
   if( ... )
     code;

   else if( ... )
     code;

   else if( ... )
     code;


Aber eigentlich ist das die falsche Fragestellung. Die korrekte 
Fragestellung für dich sollte eigentlich lauten: Bei welcher Lösung habe 
ich den geringeren Wartungsaufwand, wenn sich der von den Bedingungen 
abhängige Codeteil verändert. Und bei dieser Frage steht es dann 
plötzlich 15:1 für die ODER Lösung.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und dann gäbe es da noch eine Möglichkeit, die von der Laufzeit her 
etwas schlechter ist, aber deutliche Vorteile bezüglich der Codegröße 
hat (z.B. 240 Bytes weniger als Beispiel 1):
unsigned char i;
for ( i=0; i<15 && variable[i]; i++ );
if ( i < 15 )
    test = "BlaBlaBLa";

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan Ernst schrieb:
> Und dann gäbe es da noch eine Möglichkeit, die von der Laufzeit her
> etwas schlechter ist, aber deutliche Vorteile bezüglich der Codegröße
> hat (z.B. 240 Bytes weniger als Beispiel 1):
>
> unsigned char i;
> for ( i=0; i<15 && variable[i]; i++ );
> if ( i < 15 )
>     test = "BlaBlaBLa";
> 

Machs doch wenigstens lesbar
unsigned char i; //Warum ein char für eine Zählvariable...
for (i=0; i<15; i++)
{
    if (variable[i] != 0)
        break;
}

if (i < 15)
    test  = "BlaBlaBla"; //Wie soll das eigentlich funktionieren?

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
1) "Lesbarkeit" ist meist reine Geschmackssache. Ich finde meine 
Variante lesbarer. Der direkte Zusammenhang von for und if wird dort 
deutlicher. Bei deiner Variante sehen auf den ersten Blick for und if 
wie zwei unabhängige Codeteile aus.

2) Deine Variante ist falsch.

3) Und was bitte soll das "wenigstens" bedeuten? Was gibt es denn an dem 
Code noch alles auszusetzen?

4) Was hast du gegen ein unsigned char als Zählervariable?

Autor: Stephan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für eure schnellen Antworten. Ich hab die schnellste Möglichkeit 
gefunden, ich kann die if-Abfrage/n weg lassen da ich schon die Abfrage 
unbewusst vorher programmiert habe.

Dank euch.
Gruß
Stephan

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan Ernst schrieb:
> 1) "Lesbarkeit" ist meist reine Geschmackssache. Ich finde meine
> Variante lesbarer. Der direkte Zusammenhang von for und if wird dort
> deutlicher. Bei deiner Variante sehen auf den ersten Blick for und if
> wie zwei unabhängige Codeteile aus.
Die Funktionsweise deines Algorithmusses liegt komplett in einer Zeile. 
Ich musste zumindest zwei mal lesen um zu sehen wie es funktioniert. 
M.m.n. ist es besser das etwas zu strecken über mehrere Zeilen.

> 2) Deine Variante ist falsch.
Jaja, ich nehme an du meinst den Vergleich. Der müsste auf == 0 prüfen.

> 3) Und was bitte soll das "wenigstens" bedeuten? Was gibt es denn an dem
> Code noch alles auszusetzen?
Wenigstens im Sinne "Wenn du schon einen kompakten Algorithmus lieferst" 
;)

> 4) Was hast du gegen ein unsigned char als Zählervariable?
char kommt von Character und das heißt Zeichen. Eine Zählvariable ist 
kein Zeichen.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Simon K.
> > 4) Was hast du gegen ein unsigned char als Zählervariable?

> char kommt von Character und das heißt Zeichen. Eine Zählvariable ist
> kein Zeichen.

was nimmst du denn für eine 8bit Zahl ohne vorzeichen?

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Die Funktionsweise deines Algorithmusses liegt komplett in einer Zeile.
Und er funktioniert nicht :-/

Denn schon beim ersten Durchlauf ist die erste Bedingung i<15 erfüllt, 
die zweite aber nicht, wenn z.B. variable[1]!=0 ist. Weil aber im 
Original eine Veroderung gefordert wird, geht das schief.
Richtig wäre:
unsigned char i;
for ( i=0; i<15 && !variable[i]; i++ );
if ( i < 15 )
    test = "BlaBlaBLa";

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Simon K. schrieb:

>> 4) Was hast du gegen ein unsigned char als Zählervariable?
> char kommt von Character und das heißt Zeichen. Eine Zählvariable ist
> kein Zeichen.

Dann verstecke halt das "Character" hinter einem uint8_t.

Wenn der OP in seiner Frage nicht die stdint-Typen verwendet, dann 
verwende ich sie bei Code-Vorschlägen normalerweise auch nicht, um ihn 
nicht zusätzlich zu verwirren.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan Ernst schrieb:
> Simon K. schrieb:
>
>>> 4) Was hast du gegen ein unsigned char als Zählervariable?
>> char kommt von Character und das heißt Zeichen. Eine Zählvariable ist
>> kein Zeichen.
>
> Dann verstecke halt das "Character" hinter einem uint8_t.
Da gibt es nichts zu verstecken. Nicht mal in der stdint.h 
Implementierung der avr-libc kommt ein unsigned char bei der Deklaration 
von uint8_t vor.

> Wenn der OP in seiner Frage nicht die stdint-Typen verwendet, dann
> verwende ich sie bei Code-Vorschlägen normalerweise auch nicht, um ihn
> nicht zusätzlich zu verwirren.
Habe ich ja auch nicht. Habs nur angemerkt.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lothar Miller schrieb:
>> Die Funktionsweise deines Algorithmusses liegt komplett in einer Zeile.
> Und er funktioniert nicht :-/
Ich korrigiere mich:
der Code passt, ich hatte statt || ein && gelesen  :-/
Es ist aber auch schon spät...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Simon K. schrieb:

>> Dann verstecke halt das "Character" hinter einem uint8_t.
> Da gibt es nichts zu verstecken. Nicht mal in der stdint.h
> Implementierung der avr-libc kommt ein unsigned char bei der Deklaration
> von uint8_t vor.

Kannst du genauer ausführen, was du meinst?
Schaue ich in meine stdint.h, dann steht da

typedef unsigned char uint8_t;

In C sollte man aber auch im Hinterkopf behalten, dass char, signed char 
und unsigned char anders funktionieren als in den meisten anderen 
Sprachen. Tatsächlich ist in C ein char (und Konsorten) ein kleiner 
Integer, der bei den Standard-IO Sachen anders behandelt wird. Das ist 
per Design so und auch so beabsichtigt.

Die Argumentation, dass char (und vor allen Dingen signed char und 
unsigned char) ausschliesslich für Zeichenverarbeitung reserviert sind, 
ist in C bei weitem nicht gegeben.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Simon K. schrieb:
>
>>> Dann verstecke halt das "Character" hinter einem uint8_t.
>> Da gibt es nichts zu verstecken. Nicht mal in der stdint.h
>> Implementierung der avr-libc kommt ein unsigned char bei der Deklaration
>> von uint8_t vor.
>
> Kannst du genauer ausführen, was du meinst?
> Schaue ich in meine stdint.h, dann steht da
>
> typedef unsigned char uint8_t;

Das ist für die Doxygen Doku.

Guck mal drunter:
typedef unsigned int uint8_t __attribute__((__mode__(__QI__)));

Und das Int hat auch nicht viel zu sagen:

---
The base type int is effectively ignored by the compiler, the actual 
properties of the new type v4si are defined by the _attribute_. It 
defines the machine mode to be used; for vector types these have the 
form VnB; n should be the number of elements in the vector, and B should 
be the base mode of the individual elements. The following can be used 
as base modes:
---
http://www.delorie.com/gnu/docs/gcc/gcc_80.html

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Simon K. schrieb:
> Stefan Ernst schrieb:
>> 1) "Lesbarkeit" ist meist reine Geschmackssache. Ich finde meine
>> Variante lesbarer. Der direkte Zusammenhang von for und if wird dort
>> deutlicher. Bei deiner Variante sehen auf den ersten Blick for und if
>> wie zwei unabhängige Codeteile aus.
> Die Funktionsweise deines Algorithmusses liegt komplett in einer Zeile.

Nein, es sind zwei Zeilen. Und das ist auch der Punkt, der Algorithmus 
besteht aus for und if. Bei deiner Variante hat die for-Schleife einen 
Körper und ist meilenweit vom if entfernt (auch noch mit einer Leerzeile 
dazwischen). Das suggeriert auf den ersten Blick, dass die Schleife 
irgendetwas wiederholt ausführt und dass das if nicht direkt dazu 
gehört. Bei mir ist die Schleife leer und steht direkt vor dem if. Die 
Tatsache, dass for und if eine Einheit bilden und im for lediglich das i 
für den Vergleich vorbereitet wird, kommt damit wesentlich deutlicher 
rüber. Dass man dann bei diesem "Vorbereiten" vielleicht zweimal 
hinschauen muss, finde ich eher zweitrangig, insbesondere da ich so eine 
Konstruktion immer mit einem Kommentar versehen würde (if any 
variable[x] equals 0).

Aber wie bereits gesagt, Lesbarkeit ist zum großen Teil Geschmackssache.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan Ernst schrieb:

> Aber wie bereits gesagt, Lesbarkeit ist zum großen Teil Geschmackssache.

Agreed.

Wie wärs mit
for (unsigned char i=0; i<15; i++)
{
    if (variable[i] != 0)
    {
        test  = "BlaBlaBla"; //Wie soll das eigentlich funktionieren?
        break;
    }
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Simon K. schrieb:

>> typedef unsigned char uint8_t;
>
> Das ist für die Doxygen Doku.
>
> Guck mal drunter:

OK.
Hab ich übersehen.

Formal hast du damit recht.
Wenn allerdings die avr-libc Entwickler sich die Mühe machen, in der Dok 
einen uint8_t als unsigned int erscheinen zu lassen und es im Verhalten 
zu einem unsigned char keinen Unterschied gibt, dann würde ich sage: 
Sieht aus wie eine Ente, quackt wie eine Ente, watschelt wie eine Ente 
-> ist eine Ente.

>
> typedef unsigned int uint8_t __attribute__((__mode__(__QI__)));
> 

Als nicht gcc-Entwickler sagt mir das nichts.
Müsste man dasselbe in Standard-C ausdrücken, so würde man wohl
typdef unsigned char uint8_t;
nehmen. Und ich denke mal, ich liege nicht allzufalsch, wenn ich sage, 
dass die Mehrzahl der stdint.h Implementierungen genau das tun und auch 
das ISO-Gremium nichts dagegen einzuwenden hätte.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:

> Wie wärs mit

Mit einem == statt dem != könnte ich auch mit dieser Version leben. ;-)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan Ernst schrieb:
> Karl heinz Buchegger schrieb:
>
>> Wie wärs mit
>
> Mit einem == statt dem != könnte ich auch mit dieser Version leben. ;-)


Ähm.
Nimms als künstlerische Freihet :-)
Danke für die Korrektur

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> OK.
> Hab ich übersehen.
>
> Formal hast du damit recht.
Ja, nur als Beweis zu meiner obigen Aussage. Ansonsten nicht so wichtig 
;)

> Wenn allerdings die avr-libc Entwickler sich die Mühe machen, in der Dok
> einen uint8_t als unsigned int erscheinen zu lassen und es im Verhalten
> zu einem unsigned char keinen Unterschied gibt, dann würde ich sage:
> Sieht aus wie eine Ente, quackt wie eine Ente, watschelt wie eine Ente
> -> ist eine Ente.
Sehe ich nicht so. Obige Aussage war, dass man einen unsigned char 
hinter einem uint8_t versteckt. Daraus interpretiere ich, dass es 
unerheblich ist, ob man nun unsigned char oder den "Umweg" uint8_t 
nimmt.
Das ist es aber nicht. Höchstens syntaktisch.
Mit dem Datentyp gibt man ja nicht nur dem Compiler an, welcher Datentyp 
benutzt werden soll, sondern man sagt auch allen indirekt im Code aus, 
wofür eine Variable gedacht sein soll. Das heißt ich füge ohne große 
Umwege zusätzliche nützliche und hilfreiche Informationen dem Code 
hinzu. Oder etwa nicht? Darum geht's mir. Auch wenns Geschmackssache ist 
und ich hier nicht versuche jemanden zu überzeugen. Wie gesagt, es war 
nur angemerkt oben in einem Kommentar ;)

>>
>> typedef unsigned int uint8_t __attribute__((__mode__(__QI__)));
>> 
>
> Als nicht gcc-Entwickler sagt mir das nichts.
Mir auch nicht :-) War nur als Beweis zu der Aussage oben, auch wenn das 
jetzt nen bisschen albern ist von mir :-)

> Müsste man dasselbe in Standard-C ausdrücken, so würde man wohl
> typdef unsigned char uint8_t;
> nehmen. Und ich denke mal, ich liege nicht allzufalsch, wenn ich sage,
> dass die Mehrzahl der stdint.h Implementierungen genau das tun und auch
> das ISO-Gremium nichts dagegen einzuwenden hätte.
Ist ja auch alles kein Problem, es ging mir gar nicht im Detail darum, 
wie man sich den uint8_t Typen jetzt erzeugt, sondern wie man diesen wo 
und warum einsetzt (einsetzen sollte).

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.