a && b, wie eerst?

algemene C code
Berichten: 2
Geregistreerd: 12 Mei 2013, 20:09

a && b, wie eerst?

Berichtdoor memetica » 12 Mei 2013, 21:49

if (a && b)

Volgens de GNU compiler wordt a eerst uitgevoerd en als a == TRUE, b niet meer geëvalueerd
Hoe werkt dat bij de arduino compiler?

Ik kan nergens een antwoord vinden.

Advertisement

Gebruikers-avatar
Berichten: 188
Geregistreerd: 23 Dec 2011, 00:12

Re: a && b, wie eerst?

Berichtdoor Duality » 13 Mei 2013, 18:10

under arduino zit de gcc/g++ compiler verstopt.

Gebruikers-avatar
Berichten: 229
Geregistreerd: 20 Jan 2013, 12:01

Re: a && b, wie eerst?

Berichtdoor astrofrostbyte » 15 Mei 2013, 02:36

Bedoel je niet Logical OR ?, if ( a || b )
Vindt het toch raar dat b niet meer geevalueerd zou worden als 'a' TRUE is, denk dat het ook wel afh. is van optimize settings van de compiler.
Gear: Arduino- Uno,Due,Ethernet,Mega2560 , OLS LogicAnalyser, TDS1002, Rigol DG1022, J-Link EDU, BusPirate

Gebruikers-avatar
Berichten: 5043
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: a && b, wie eerst?

Berichtdoor nicoverduin » 15 Mei 2013, 22:23

memetica schreef:if (a && b)

Volgens de GNU compiler wordt a eerst uitgevoerd en als a == TRUE, b niet meer geëvalueerd
Hoe werkt dat bij de arduino compiler?

Ik kan nergens een antwoord vinden.

Je hebt dit toch ook achterhaald? heb je in de source van de compiler gekeken?

Volgens de gcc reference zie: http://www.gnu.org/software/gnu-c-manua ... -Operators par. 3.7 klopt het wat je zegt. En op zich niets mis mee. Waarom zou je verder controleren als de uitkomst toch hetzelfde blijft.
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Gebruikers-avatar
Berichten: 229
Geregistreerd: 20 Jan 2013, 12:01

Re: a && b, wie eerst?

Berichtdoor astrofrostbyte » 16 Mei 2013, 20:00

goh, duidelijk die link, Totaal niet verwacht dat bij: if ( a && b++) , de b++ niet uitgevoerd zal worden bij a=0
Gear: Arduino- Uno,Due,Ethernet,Mega2560 , OLS LogicAnalyser, TDS1002, Rigol DG1022, J-Link EDU, BusPirate

Berichten: 85
Geregistreerd: 10 Jan 2013, 14:51
Woonplaats: Waddinxveen

Re: a && b, wie eerst?

Berichtdoor Karel » 17 Mei 2013, 12:48

astrofrostbyte schreef:goh, duidelijk die link, Totaal niet verwacht dat bij: if ( a && b++) , de b++ niet uitgevoerd zal worden bij a=0


Dat is wel zo gedefinieerd in Kernighan and Ritchie, de oorspronkelijke auteurs van de taal C.
Het kan gebruikt worden om hele vieze one-liners te schrijven. Een one-liner is een programma in 1 regel. Bij de Arduino niet van toepassing, omdat wij alleen maar twee voorgeschreven functies hoeven te definieren.

Het is heel makkelijk om in C volstrekt onleesbare/onbegrijpelijke code te schrijven. Het is veel moeilijker om begrijpelijke code te schrijven. Er kan dan ook bijna nooit teveel commentaar in een stuk code worden opgenomen. Ik ben wel eens een jaar na het oorspronkelijk schrijven van een zeer complexe functie (15.000 regels C, alleen die functie plus ondersteundende library!) wat in die functie gaan aanpassen. Ik denk van mezelf dat ik best redelijk heldere code schrijf, en ik maak veel gebruik van commentaar, maar toch liep ik een paar keer aan tegen een stuk waarvan ik dacht, wat is in hemelsnaam het effect hiervan?

Ik heb wel eens op een forum een domme vraag 'Hoe stop ik mijn unix systeem' (ja, sommige vragen zijn dom, tenminste op fora. Dat is vragen naar de bekende weg zonder de geringste moeite te nemen eerst een handleiding te raadplegen) zien beantwoorden in de trant van:

"
log in als root
type vi<ENTER>
type imain (){ /* code die eerst de schijven wist en dan het systeem afzet */}
type <ESC>
type :wstop.c<ENTER>
type :q<ENTER>
type cc stop.c -o stop<ENTER>
type stop <ENTER>
De schijven zullen nu even gaan rammelen, en uiteindelijk gaat het systeem uit.
"

Op de plaats van dat commentaar stond dan een reeks ingewikkelde && en || tests, die samen het 'gewenste' resultaat opleverden.
If you think education is expensive, try ignorance! (Derek Bok)

Gebruikers-avatar
Berichten: 229
Geregistreerd: 20 Jan 2013, 12:01

Re: a && b, wie eerst?

Berichtdoor astrofrostbyte » 17 Mei 2013, 17:25

Is dit iets wat bij andere programmeer talen ook te verwachten is ?.
Gear: Arduino- Uno,Due,Ethernet,Mega2560 , OLS LogicAnalyser, TDS1002, Rigol DG1022, J-Link EDU, BusPirate

Berichten: 85
Geregistreerd: 10 Jan 2013, 14:51
Woonplaats: Waddinxveen

Re: a && b, wie eerst?

Berichtdoor Karel » 17 Mei 2013, 18:00

Wat bedoel je, zo'n one-liner die schade aanricht? Dat heeft in het voorbeeld meer met vraagstelling te maken, en klakkeloos overtypen wat er wordt geantwoord.

Of bedoel je die bewerkingsvolgorde? Dat hangt van de taaldefinitie af. In Pascal staat de evaluatievolgorde niet vast. Tenminste niet in de Pascal-versies waarmee ik in 1980 programmeren leerde en in later jaren veel heb gewerkt. In Pascal mag je er dus niet van uitgaan dat bij "a || b" b niet wordt uitgevoerd als a TRUE is.
Pascal heeft bijvoorbeeld, i.t.t. 'C', range-checking, d.w.z. geeft een fout als je met een index buiten de gedefinieerde grootte van een array een element probeert te lezen of te schrijven, of een string te lang probeert te maken. Bij zeer tijdkritische programma's schakelden we de rangechecking na de testperiode uit d.m.v. een compileroptie. Waarom? omdat dat instructies scheelt in de gegenereerde code, er wordt niet meer bij iedere assignment en iedere leesoperatie op een array eerst code uitgevoerd om te controleren of de indexwaarde wel klopt.

Zo hadden we in die pascal-variant ook een truc om een functie-aanroep goedkoper te maken. Declareer je een functie met 4 parameters, dan roep je die ook met 4 parameters aan. Die 4 parameters worden bij de aanroep eerst 1 voor 1 op de stack gezet, en daarna gaat de programmapointer verder op het entry-punt van de functie. Daar worden de variabelen weer van de stack afgehaald. Wij definieerden 1 variabele in de functieaanroep, en zorgden ervoor dat de variabelen zowel in de aanroepende als in de aangeroepen functie achter elkaar werden gedefinieerd. Dan wisten we dat de geheugenlocaties van deze variabelen aaneengesloten in het geheugen lagen. Dan riepen we de functie aan met alleen de eerste parameter als variabele. Doordat ze aaneengesloten in het geheugen lagen waren ze daarmee ook alle 4 bekend in de aangeroepen functie.

Zo kan je met gedetailleerde kennis van de programmeertaal nogal wat shortcuts bedenken. Nu is pascal ontworpen als taal voor programmeer-onderwijs, en daarin staat verwerkingssnelheid niet voorop, maar wel robuustheid. Als verwerkingssnelheid in een commercieel project dan wel een issue wordt, moet je wat maatregelen nemen. Maar dat maakt de resulterende software foutgevoeliger, en onderhoud is ook een stuk complexer geworden. Dit speelde bij de bouw van een programmeertaal/tool, ik werkte op de R&D afdeling die zich daarmee bezig hield. Dan kan je, mits goed gedocumenteerd, zulke keuzes verantwoorden.

C is een veel 'gevaarlijker' taal. Voer je een assignment uit via een pointer, en wijst die pointer toevallig naar een willekeurige plek in het geheugengedeelte dat je executable bevat, dan overschrijf je gewoon een stukje code. 'results are unpredictable' is dan het devies. Ik heb t.b.v. de eerder aangehaalde C-functie van 15000 regels zelf een range-checking library gebouwd (het omgekeerde van pascal dus, C heeft het niet en ik voegde het toe). Het bedenken en schrijven van die range-checking heeft me 2 nachten en een dag gekost. Maar ik had daarna wel binnen 10 minuten een geheugenlek boven water, waar ik al 2 weken naar op zoek was.

de if (a && b) laat zich bijvoorbeeld handig gebruiken als je een reeks bewerkingen wil doen, maar zodra een bewerking fout gaat wil je stoppen en een foutmelding geven:

Code: Alles selecteren
dowhat()
{
  int err = 0; /* de variabele voor de foutwaarde */

  if (err || err=functie1() ) ; /* als err == 0 wordt functie1 uitgevoerd. het resultaat van */
                                /* functie1 wordt in err opgeslagen. Ongeacht de uitkomst,   */
                                /* na de if() staat een ';', een empty statement             */


  if (err || err=functie2() ) ; /* als err == 0 wordt functie2 uitgevoerd. het resultaat van */
                                /* functie2 wordt in err opgeslagen. Ongeacht de uitkomst,   */
                                /* na de if() staat een ';', een empty statement             */

  if (err || err=functie3() ) ; /* als err == 0 wordt functie3 uitgevoerd. het resultaat van */
                                /* functie2 wordt in err opgeslagen. Ongeacht de uitkomst,   */
                                /* na de if() staat een ';', een empty statement             */

  if (err)
  {
     /* voer een of andere foutmelding/logging procedure uit /*
  }

}


Wat is nu het voordeel van deze constructie? Dat laat ik even sudderen, ik ga nu eerst een weekendje weg met vrouw, kinderen en kleinkinderen ;-). Ik ben benieuwd of dat voordeel gevonden wordt.
Tot later, Karel
If you think education is expensive, try ignorance! (Derek Bok)

Berichten: 85
Geregistreerd: 10 Jan 2013, 14:51
Woonplaats: Waddinxveen

Re: a && b, wie eerst?

Berichtdoor Karel » 17 Mei 2013, 18:40

oh ja,

Code: Alles selecteren
if (err || err=functie1() ) ;


kan eleganter:

Code: Alles selecteren
err = err || functie1();


(zat een beetje ver weg in mijn geheugen)
If you think education is expensive, try ignorance! (Derek Bok)

Berichten: 85
Geregistreerd: 10 Jan 2013, 14:51
Woonplaats: Waddinxveen

Re: a && b, wie eerst?

Berichtdoor Karel » 21 Mei 2013, 20:25

Het is niet erg ingewikkeld. Door een reeks statements als

Code: Alles selecteren
err = err || functie1();
err = err || functie2();
err = err || functie3();


te gebruiken wordt ervoor gezorgd dat na een fout in een van de functies de erna volgende functies niet meer worden uitgevoerd. Op deze manier is het eenvoudig een serie bewerkingen te stoppen zonder een ingewikkelde geneste if () then ; elsif ; te schrijven. Ook is het eenvoudig om er een functie tussen te voegen of tussenuit te halen. Bovendien wordt vermeden om na iedere functie de foutstatus uit te vragen, en dan met een goto statement naar het einde van de bewerkingen te springen.

Groet, Karel
If you think education is expensive, try ignorance! (Derek Bok)

Terug naar C code

Wie is er online?

Gebruikers in dit forum: Geen geregistreerde gebruikers en 15 gasten