Hi guys,

Ik probeer te begrijpen wat onderstaand commando doet.

Het gaat me vooral om de regel: x *= y - 1
Ik kan die *= niet plaatsen.

Iemand een idee?

Mvg
Fantomaz

De meeste operatoren kunnen gecombineerd worden met een toekenning.

a += b;     // a = a + b;
a *= b;
a *= b + c; // a = a * (b + c);    Let op! de toewijzing en bijbehorende operator komen dus als laatste!
a /= b;     //a = a / b;
a &= 5;     //a = a & 5;

Deze zijn toegestaan: += -= *= /= %= <<= >>= &= ^= |=

Door dit soort constructies noemen ze C een 'WORN' (Write Once Read Never) language... :+

Onzin, dit is prima leesbaar voor iedereen die één keer de moeite wil nemen om te begrijpen hoe het werkt. In ieder geval beter dan "goto hell"

Dit is een typisch *waarom doe je dat??* ding. Waren die twee toetsaanslagen extra echt iets wat opgelost moest worden? En dat ten koste van de leesbaarheid?

Het is helemaal niet ten koste van leesbaarheid, het verbeterd de leesbaarheid juist enorm, want nu hoef ik niet te gaan vergelijken of één van de variabelen aan de rechterkant hetzelfde is als de variabele aan de linkerkant van de vergelijking.

CalibrationReturnstate |= CAL_SUCCES_CH1;

Is toch veel beter leesbaar dan

CalibrationReturnState = CalibrationReturnStatus | CAL_SUCCES_CH1;

Op vrijdag 4 oktober 2024 21:45:32 schreef Sine:
Dit is een typisch *waarom doe je dat??* ding. Waren die twee toetsaanslagen extra echt iets wat opgelost moest worden? En dat ten koste van de leesbaarheid?

Iemand die regelmatig met C(++) of Java werkt, heeft echt geen probleem met die syntax. Waarom schrijven Engelsen isn't in plaats van is not? Dat zijn nu eenmaal eigenaardigheden van een taal. Tot nader order zijn C, basic, Java, cobol, ... nog altijd programmeer talen.

Zo kan je er wel meer bedenken.


for(uint8_t cnt = 0; cnt < 10; cnt++){

}

Kan je ook schrijven als


uint8_t cnt = 0;
while(cnt < 10){

   cnt = cnt + 1; 
}
String str = (a==b?"Waar":"Onwaar"); 

Kan je ook gaan schrijven als


String str;
if(a==b){
  str = "Waar";
}
else{
  str = "Onwaar";
}

Waarom? Vraag het aan de makers.

Geef mij maar Delphi:

for cnt := 0 to 9 do

Bij C moet je altijd even nadenken wat er precies gebeurt. Bij Delphi en ook het oude PLM zie je het meteen, geen vergissing mogelijk.

Kan ook in een while loop maar waarom zou je. For is duidelijker.

En ook volgens mij hoort het x = x * (y-1) te zijn.

Ik weet dat er mensen zijn die een constructie als
String str = (a==b?"Waar":"Onwaar");
prachtig vinden. Maar ik niet echt (alhoewel ik deze toch wel leesbaar vind). Als ik moet reviewen wil ik duidelijke taal, meteen leesbaar. En vooral daar waar het wat onduidelijk is wat commentaar erbij. Hou het simpel en leesbaar. De code die de compiler genereert wordt niet beter van hoogstandjes, het optimaliseert tot hetzelfde. Minder regels sourcecode leiden niet tot minder programmacode. Kunstwerken leiden alleen maar tot denkfouten.

Ook dat ben ik van mening dat het juist duidelijker wordt; in alle gevallen gaat het resultaat naar str. Als je het als een if-else gaat schrijven moet je gaan vergelijken of de variabele waar naar geschreven wordt hetzelfde is. Met een korte naam als "str" gaat natuurlijk wel, maar die naam is voor mij juist fout omdat hij het doel niet beschrijft.

Neem deze regel:

HostData[ DeviceIndex ].Axes[ AXIS_X ].Increment = Actual > Target ? 1 : -1;

Of deze:

if( Actual > Target )
    HostData[ DeviceIndex ].Axes[ AXIS_X ].Increment = 1
else
    HostData[ DeviceIndex ].Axes[ AXIS_Y ].Increment = -1;

Dan vind ik de eerste optie duidelijker.

Ik de tweede.
Nu maakt het niet uit welke versie je intypt. De compiler compileert beide naar dezelfde code. Oude compilers deden dat niet en in die tijd waren bitjes heel duur.
Vroeger mocht een naam maximaal acht karakters groot zijn. Nu steekt het niet zo krap.
Code schrijf je niet voor jezelf, maar voor een ander, dus je moet schrijven op de ander zijn of haar kennisniveau.

Op vrijdag 4 oktober 2024 21:04:03 schreef Arco:
Door dit soort constructies noemen ze C een 'WORN' (Write Once Read Never) language... :+

Met een beetje pech kan je na een paar jaar (maanden) niet eens je eigen code lezen.

Op vrijdag 4 oktober 2024 21:59:17 schreef SparkyGSX:

CalibrationReturnstate |= CAL_SUCCES_CH1;

Is toch veel beter leesbaar dan

CalibrationReturnState = CalibrationReturnStatus | CAL_SUCCES_CH1;

En het doet ook hele andere dingen. :+

[Bericht gewijzigd door ohm pi op (18%)]

Wat is dat C toch een allemachtig mooie taal! Of je nou een tooltje wilt knutselen voor DOS, Windows of Linux, een kleine 8 bit microcontroller wilt programmeren, of juist een dikke ARM Cortex M. Met C kan het allemaal. Het is de multimeter onder de programmeertalen. Schitterend gewoon! ;)

Op vrijdag 4 oktober 2024 23:04:42 schreef PE9SMS:
Wat is dat C toch een allemachtig mooie taal! Of je nou ...

Maar bedoel je dan echt de taal of de beschikbare libraries, compilers e.d. de ecosfeer..

PHP vind ik bijvoorbeeld geen mooie taal, maar als ik binnen 2 uur een specifiek bestelformuliertje met login en password reset met sms moet bouwen dan pak(te) je (vroeger) bijvoorbeeld wordpress met php. Met C gaat dat lastig worden.

Ik vind i++ , i =+ x e.d. wel fijn om mee te werken. Ja soms is langere notatie helderder, dat is waar.

Op vrijdag 4 oktober 2024 23:02:17 schreef ohm pi:
Vroeger mocht een naam maximaal acht karakters groot zijn.

Het waren er 6.

Die ? constructie is toch het handigst in veel gevallen, zie dit voorbeeld:


if (a==b)
{
  printf("Waar");
}
else
{
  printf("Onwaar");
}

De printf staat er nu 2 keer in.

Het "Do Not Repeat Yourself principle":


  printf( (a == b) ? "Waar" : "Onwaar");

Nu is die printf vrij kort, maar als de functienaam wat langer is wordt het al snel rommelig.

En nog een plaats waar je altijd de ? moet gebruiken is als je een const variable moet assignen, dan ontkom je er niet aan.

Op vrijdag 4 oktober 2024 23:04:42 schreef PE9SMS:
Wat is dat C toch een allemachtig mooie taal! Of je nou een tooltje wilt knutselen voor DOS, Windows of Linux, een kleine 8 bit microcontroller wilt programmeren, of juist een dikke ARM Cortex M. Met C kan het allemaal. Het is de multimeter onder de programmeertalen. Schitterend gewoon! ;)

Eerlijk gezegd vind ik C een outdated taal. Het is een heel oude programmeertaal, uit 1972! Het zou zoveel beter en vooral leesbaarder kunnen.

Het voordeel van C is dat alles kan. En dat is dan ook weer het nadeel: teveel kan.

Op vrijdag 4 oktober 2024 23:02:17 schreef ohm pi:
En het doet ook hele andere dingen. :+

Dat was niet per ongeluk, het punt is dat je heel goed moet lezen om dat te zien, in het tweede voorbeeld. Bij de eerste, korte syntax gaat het altijd goed, en dus kun je die veel sneller lezen en analyseren.

Code schrijf je niet voor jezelf, maar voor een ander, dus je moet schrijven op de ander zijn of haar kennisniveau.

Precies! Ik verwacht minimaal een matig competente programmeur, met minstens drie hersencellen en een bereidheid er twee tegelijk in te zetten. Als iemand deze basale kennis niet heeft, wil ik helemaal niet dat die persoon aan mijn code zit, want als het dan niet meer werkt moet ik het waarschijnlijk weer gaan oplossen.

Als programmeur vind ik deze schrijfwijze heel duidelijk:

a *= b;

Voor mij is het belangrijker dat functies overzichtelijk blijven. Het moet in één oogopslag duidelijk zijn wat er gebeurt in een functie. Vermijd diepe nestingen of "loops in loops". Vaak kun je zulke dingen oplossen met kleinere, goed gedefinieerde functies of door gebruik te maken van early returns.

Het voorbeeldje van sparky op zichzelf is misschien niet zo heel mooi. Maar als er meerdere regels achter elkaar staan wordt het ineens een stuk duidelijker.


HostData[ DeviceIndex ].Axes[ AXIS_X ].Increment = ActualX > TargetX ? 1 : -1;
HostData[ DeviceIndex ].Axes[ AXIS_Y ].Increment = ActualY > TargetY ? 1 : -1;
HostData[ DeviceIndex ].Axes[ AXIS_Z ].Increment = ActualZ > TargetZ ? 1 : -1;

Ik weet het datatype en de exacte bedoeling niet, en het is maar een voorbeeldje natuurlijk. Maar "actual == target" valt nu buiten de boot, het kan zo bedoeld zijn, maar als je deze case ook wilt oplossen. (Uiteraard rekening houden met overflows en er even uitgaande dat deze macro ergens anders gedefinieerd is.)


HostData[ DeviceIndex ].Axes[ AXIS_X ].Increment = LIMIT(TargetX - ActualX, -1, 1);
HostData[ DeviceIndex ].Axes[ AXIS_Y ].Increment = LIMIT(TargetY - ActualY, -1, 1);
HostData[ DeviceIndex ].Axes[ AXIS_Z ].Increment = LIMIT(TargetZ - ActualZ, -1, 1);

Om weer terug te keren naar de oorspronkelijke vraag, wat dacht je van zo iets?


uint8_t result = 0;
result += pin_0 ? 0x01 : 0;
result += pin_1 ? 0x02 : 0;
result += pin_2 ? 0x04 : 0;
result += pin_3 ? 0x08 : 0;
result += pin_4 ? 0x10 : 0;
result += pin_5 ? 0x20 : 0;
result += pin_6 ? 0x40 : 0;
result += pin_7 ? 0x80 : 0;

Hoewel C een krachtige taal is, blijft het een onderwerp van discussie. Het feit dat je code op verschillende systemen kunt compileren, komt niet per se door de taal zelf. Persoonlijk vind ik het gehannis met strings, arrays en pointers minder mooi. Een kleine aanpassing in je code kan onverwachte effecten hebben, iets waar je als programmeur eigenlijk niet mee bezig zou willen zijn. Laat dat werk over aan de optimizer en compiler (Oke, er zijn wat uitzonderingen, zeker in de embedded wereld, waar je wel grip op de zaak wilt.).

Om even terug te keren naar arrays, ik vind het niet handig dat de lengte niet blijft bestaan. Ik snap dat dit anders ergens in ram ruimte kost, en ram is duur, zeker in de tijd dat C ontwikkeld is.

C valt nog mee, maar C++ brengt veel meer complexiteit met zich mee: gewone pointers, smart pointers, referenties (wel of geen const), initialisatie via de constructor, de levensduur van objecten... Je moet heel scherp blijven. Vaak zie je dat de taal niet netjes gebruikt wordt, zoals het correct toepassen van const, enum, en andere best practices die vaak over het hoofd worden gezien.

'Krachtige taal' is niet hetzelfde als 'ultra korte notatie'... :+

Alle moderne programmeertalen zijn zo'n beetje gelijk wat betreft de gegenereerde code. (ze hebben meestal hetzelfde bsck-end, alleen het frontend is anders)
C is een van de weinige talen waarbij ik bij zulke kromme notaties altijd de C language reference erbij moet halen...

Ik vind het meer gemakzucht van de programmeur omdat die te beroerd is om een paar letters meer in te typen.
Bij goede code (ongeacht de taal) moet je zonder manual uit de code op kunnen maken wat er precies gebeurt.


result += pin_0 ? 0x01 : 0;

is in basic


result = result + (pin_0 = 0x01)

Weinig langer en meteen duidelijk.

Op vrijdag 4 oktober 2024 21:45:32 schreef Sine:
Dit is een typisch *waarom doe je dat??* ding. Waren die twee toetsaanslagen extra echt iets wat opgelost moest worden? En dat ten koste van de leesbaarheid?

VOOR DE LEESBAARHEID!!!!

Je ziet al in een aantal voorbeelden dat er haakjes nodig zijn om de juiste expressie te krijgen. Dan is "x *= y-1" leesbaarder dan x = x * (y - 1) ...

Op vrijdag 4 oktober 2024 21:08:28 schreef SparkyGSX:
voor iedereen die één keer de moeite wil nemen om te begrijpen hoe het werkt.

Op zaterdag 5 oktober 2024 10:32:22 schreef Arco:


result = result + (pin_0 = 0x01)

Dat is in C:


result += pin_0 == 1;

waarbij C de verwarring voorkomt dat = en = in basic twee verschillende dingen zijn.

[PE9SMS]Wat is dat C toch een allemachtig mooie taal!

+1.

Het is ca. 25 jaar geleden dat ik ervoor koos om te stoppen met software en me (hobbymatig) toe te leggen op hardware. Het programmeren wat ik ooit deed was in BASIC, assembly (C64), Pascal (verplicht voor school, had een gruwelijke hekel aan die taal), een klein beetje Prolog maar vooral heel veel C. Die laatste taal heb ik als 15-jarige geleerd op advies een familielid dat werkzaam was in de informatica. De taal mezelf geleerd, op basis van een cursus in de vorm van een .txt-file.

Nu, 35 jaar later, krabde ik mezelf achter de oren bij het lezen van de vraag van OP: '(X *= Y-1)'; is dat niet één van de eerste dingen die in elke programmeer-cursus wordt uitgelegd? Toch in elk geval destijds wel bij C. X+=1, oftewel X=X+1. Hoe kan men hier spreken over een gebrek aan duidelijkheid?

[SparkyGSX] Onzin, dit is prima leesbaar voor iedereen die één keer de moeite wil nemen om te begrijpen hoe het werkt.

Yep. Of iedereen die één keer een cursus programmeren openslaat.

Aan OP: ik weet niet hoe u 'C' probeert te leren, maar mijn advies is, neem een goed boek. Ik heb er zojuist eventjes het 'C handboek' (Kernighan & Ritchie) bij opengeslagen, en in hoofdstuk 2 staat het grondig uitgelegd; zie foto's hieronder. Het boek kan ik van harte aanbevelen! Ik zou zelfs nog verder willen gaan door te stellen dat dit boek eigenlijk verplichte kost is. U ziet dat uw probleem er letterlijk en tot in detail uitgelegd wordt.

Succes met het leren van deze mooie en krachtige taal! Het is de tijd en energie die u erin stopt dubbel en dwars waard. Dat was het ook voor mij, die deze taal in 1989 geleerd heeft en er sinds ca. '98 nooit meer iets mee gedaan heeft, maar toch nog steeds profijt ondervindt van de opgedane kennis.

Als X+=1, oftewel X=X+1 zou zijn is volgens mijn logica Y*=1 zou dan zijn Y=Y*1.. Maar volgens REW is "x *= y-1" leesbaarder dan x = x * (y - 1)".. Waarom is X*=Y-1 dan x = x * ( y - 1 ) en niet x = ( x * y ) - 1 ? Dat zou voor mij logisch zijn, en waarom is de een dan beter leesbaarder dan de andere :S

Het boek van Leen Ammeraal is ook een uitstekend C leerboek. Is alleen niet meer zo verkrijgbaar denk ik.

Op zaterdag 5 oktober 2024 13:01:46 schreef diebobo:
Als X+=1, oftewel X=X+1 zou zijn is volgens mijn logica Y*=1 zou dan zijn Y=Y*1.. Maar volgens REW is "x *= y-1" leesbaarder dan x = x * (y - 1)".. Waarom is X*=Y-1 dan x = x * ( y - 1 ) en niet x = ( x * y ) - 1 ? Dat zou voor mij logisch zijn, en waarom is de een dan beter leesbaarder dan de andere :S

Dit gaat om de volgorde waarin C de dingen uitvoert. Alles rechts van het = teken gebeurt eerst.

Ik denk trouwens dat dit ook voor een groot deel gaat om wat je gewend bent. Als je veel C programmeert dan vind je dit waarschijnlijk heel logisch. Ben je dit niet gewend dan ziet het eruit als hekserij.

[Bericht gewijzigd door hardbass op (17%)]

De onderliggende gedachte om kost wat kost 1 letter minder in te moeten toetsen om de code veel duidelijker te maken vind ik belachelijk...

'X=X+1' is 'self explanatory' en 'X+=1 niet... (maar we hebben één letter uitgespaard... :+ )