Fantomaz
Ik moet hier weer vaker komen... Wat kun je zo'n forum als deze gaan missen. :-)
Hi Guys,
Ik heb een stukje code waarvan ik het begin niet helemaal begrijp.
Kan iemand mij daar wat wat verlichting over geven?
((x >> teller)&1) ? printf("1"):printf("0");
Dat het een vraag is waarbij positief beantwoord er "1" wordt geprint en negatief "0", was me al duidelijk.
Daarnaast heeft het iets met het shiften van bits te maken en volgens mij of er een match is met "1" (AND 1)
Tot zover. De rest is me wat onduidelijk.
anyone on this?
x >> teller -> dit schuift het getal in x, "teller" keer naar rechts.
vervolgens word alleen bit 0 bewaard.
Eigenlijk is die printf("1"):printf("0") overbodig, men had ook direct het resultaat kunnen printen.
bv. x=10100101
teller resultaat
0 1
1 0
2 1
3 0
4 0
5 1
6 0
7 1
Ik denk dat de bitjes van 'x' naar rechts worden geschoven, 'teller' maal (wat erop neerkomt dat 'x' 'teller'-maal door twee wordt gedeeld.
(Ofwel, 'x' wordt gedeeld door [2 tot de macht 'teller'].)
De bitwise AND van de resulterende 'x' met 1 geeft de LSB van die 'x'.
Als die 1 is wordt een '1' geprint, en anders een '0'.
e: wat hij ↑ zegt, dus. 
benleentje
Golden Member
Stel je hebt het binaire getal
1111 0000
1111 0000 >> 1 = 0111 1000
1111 0000 >> 2 = 0011 1100
enz
Alle bitjes worden naar rechts verschoven en hoeveel keer dat gebeurt dat is de waarde van teller.
Zo kan je heel makkelijk een 32 bit getal maken uit 4 bytes
32 bit getal is x
X = X + byte1
X << 8 ?? alles bitjes 8x naar links
X = X + byte2
X << 8
of er een match is met "1" (AND 1)
Uit ((x >> teller)&1) moet een 1 of 0 uitkomen om zo een waar of niet waar over te houden.
[Bericht gewijzigd door benleentje op (16%)]
Hoeben
Golden Member
https://www.hoeben.com https://www.overstockdevices.com https://www.asensor.eu https://www.circuitsonline.net/forum/user/4355#aanbod Voor alle verkoop: een tegenbod is altijd welkom!
Het is treurig dat programmeurs denken dat code met alles op 1 regel ook tot een meer optimaal programma leidt. Het probleem is dat door dergelijke code je bij review of wijzigen de hele tijd moet kijken 'wat doet dit ook al weer' waardoor je vertraagd wordt en overzicht verliest. Bij grotere programmas best onhandig. Voordeel is wel dat je veel op 1 pagina krijgt.
Het doel is duidelijk met de teller laten zien welk bit 0 of 1 is.
Zoals williewortel schrijft:
x >> teller, dit schuift het getal in x "teller" keer naar rechts.
&1, dit is een AND, alles weg behalve het meest rechtse bitje
?, is dit true of false (1 is true, 0 is false)
dan doe een printf("1") anders printf("0")
waar de laatste regel ook printf("een") anders printf("nul") had kunnen zijn
In pseudotaal:
if ( SHR(x,teller) &1) = 1
then print '1'
else print '0'
Arco
Special Member
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Grappig toch dat je als pseudocode meestal iets basic-achtigs ziet, omdat dat tenminste te begrijpen is... 
In dit geval is het zelfs korter en duidelijker...:
Print Str$((x>>count) And 1)
Dit is natuurlijk korter:
printf("%d",(x >> teller)&1);of:
putc(((x >> teller)&1)+'0');Maar ik ben natuurlijk gedeformeerd door 40+ jaar C/C++ programmeren op embedded spul.
Op donderdag 14 november 2024 08:12:50 schreef JoWi:
Dit is natuurlijk korter:putc(((x >> teller)&1)+'0');
Kan nog korter, behalve dat putc nog een tweede argumetn (FSTREAM*) nodig heeft
putc(((x=>>1)&1)+'0', stdout);
Maar zoals altijd bij perlC-golf, de leesbaarheid wordt enkel minder.
// print all bits of x individually
for (teller = 0; teller < sizeof(x)*8; teller++) {
if( (x >> teller) & 1) {
printf("1");
} else {
printf("0");
}
}
Als ik nu eens bovenstaand programmatje (met de verplichte void main() en #include boilerplate bouw, en vergelijk met deze:
// print all bits of x individually
for (teller = 0; teller < sizeof(x)*8; teller++) {
printf((x>>teller)&1 ? "1": "0");
}
Dan levert de eerste kleinere code op!
Link:
https://godbolt.org/#z:OYLghAFBqd5QCxAYwPYBMCmBRdBLAF1QCcAaPECAMzwBtMA…
Blijkbaar snapt de compiler leesbare code beter 
Op donderdag 14 november 2024 09:06:29 schreef blurp:
[...]
Kan nog korter, behalve dat putc nog een tweede argumetn (FSTREAM*) nodig heeft
Hangt van je compiler af, vaak is putc() een macro voor fputc().
Code wordt er niet groter of kleiner door.
>>Maar zoals altijd bij perlC-golf, de leesbaarheid wordt enkel minder.
Yep 7 regels in plaats van één. Dan is met één regel het overzicht over je code toch beter, want er staan maar een beperkt aantal regels op je beeldscherm.
En ja: ik heb een folding editor, maar dan moet ik weer op die accolade klikken.
rew
four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
Op donderdag 14 november 2024 09:06:29 schreef blurp:
Kan nog korter, behalve dat putc nog een tweede argumetn (FSTREAM*) nodig heeft
Dat is fputc, niet putc. putc(c) is equivalent met fputc (c, stdin).
Die printfs in de ? : constructie heb ik nog nooit gebruikt of gezien. Maar... moet kunnen.
Het originele stukje code is waarschijnlijk bedoeld om de waarde van x binair te printen.
for (teller=7;teller >= 0; teller--) putc ( ((x>>teller)&1)+'0');
is hoe ik het zou schrijven.
[Bericht gewijzigd door rew op (37%)]
Op donderdag 14 november 2024 10:10:28 schreef JoWi:
Hangt van je compiler af, vaak is putc() een macro voor fputc().
Dan klopt er iets niet aan je compiler. De standaard is vrij duidelijk, putc en fputc hebben allebei twee argumenten. (link naar posix want ik kan zo snel geen online ISO C standaard vinden)
putchar daarintegen gebruikt er maar een.
Yep 7 regels in plaats van één. Dan is met één regel het overzicht over je code toch beter, want er staan maar een beperkt aantal regels op je beeldscherm.
Maak er dan een (desnoods inline) functie van.
Op donderdag 14 november 2024 10:56:24 schreef blurp:
[...]
putchar daarintegen gebruikt er maar een.
OK.. putchar() ipv putc(), ik moet ook niet posten voor ik koffie op heb 
Op donderdag 14 november 2024 08:12:50 schreef JoWi:
Dit is natuurlijk korter:
Ik verbaas me al meer dan 40 jaar over al die mensen die denken dat als je minder tekst gebruikt voor je source-code je dan ook compactere object-code krijgt.
Ik spendeer liever een paar letters meer, zodat de kans dat ik (of een ander) het later begrijp groter is. Dan doet de compiler er maar 3ms langer over, ik kan er niet mee zitten. Het is ook gewoon fijn dat je de compiler kunt starten, koffie kunt halen en dat ie dan nog nét niet klaar is. 
Ik zag maandag in de trein, naast me, iemand die in code zat te bladeren. In de gauwigheidheid spotte ik een regeltje Secretcode == Secret_code. Zó krijg je echt snel allerlei fouten en misverstanden.
rew
four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
Op donderdag 14 november 2024 10:56:24 schreef blurp:
putchar daarintegen gebruikt er maar een.
Ja, die bedoel ik! Sorry. foutje bedankt. 
Op donderdag 14 november 2024 14:30:16 schreef Hensz:
[...]
Ik verbaas me al meer dan 40 jaar over al die mensen die denken dat als je minder tekst gebruikt voor je source-code je dan ook compactere object-code krijgt.
En ik verbaas me al jaren over mensen die denken dat als je het langer opschrijft het duidelijker wordt.
Ik ben er op tegen om "teller" te schrijven. Iedereen weet dat de variabele i voor "actueel gebruik als teller in een loop" bedoeld is. Dan "teller" schrijven maakt de boel alleen maar onnodig langer en onoverzichtelijker.
Die "printf" binnen de ? : constructie is zodanig ongebruikelijk dat ik die in 35 jaar C nog niet ben tegengekomen. Dat is dus een constructie waar ik even voor moest stoppen, wat nieuws moest leren constateren dat dit ook werkt en dan pas door. Dat is NIET de bedoeling voor "duidelijke code".
Van mij mag je
for (i=7;i>=0;i--) printf ("%c", ((x>>i)&1)?'1':'0');
schrijven als je dat duidelijker vind dan de '0'+ ... constructie.
Over optimalisatie: Ik doe het zeker niet zo korter om efficientere code te krijgen. Het geheel blijft overzichtelijker.
By the way... Ik heb mijn laatste code en de originele code (met een loop er omheen) in m'n compiler gestopt. Beide resulteren in een 13 instructie lange functie. (13 = incl de functie prelude en post-lude) en een 5 instructie lange loop waarbij niet printf ("%c", ...) maar putchar aangeroepen wordt!
Op donderdag 14 november 2024 14:30:16 schreef Hensz:
[...]
Ik verbaas me al meer dan 40 jaar over al die mensen die denken dat als je minder tekst gebruikt voor je source-code je dan ook compactere object-code krijgt.
Het leukste vind ik dus: Soms is het tegenovergestelde waar!
Als je de volgende code in GCC (14.2, X86-64) stopt:
if( x & 1) {
printf("1");
} else {
printf("0");
}
krijg je totaal 43 byte objectcode
Maar de kortere versie:
printf(x&1 ? "1": "0");
geeft 46 byte objectcode.
Als je naar de assembly kijkt snap je ook waarom:
GCC weet de simpele "printf("0") te vereenvoudigen tot een call naar putchar.
Maar de moeilijke printf(blah ? iets : iets) lukt hem dat niet.
Dus de compiler snapt leesbare code beter 
Voor AVR_GCC geld hetzelfde. Voor CLANG juist niet, die maakt van de kortere code ook een kortere object. Die overigens is beide gevallen groter is dan die van GCC. YMMV.
@arco: Maar als je deelt door 3 krijg je ook een ander resultaat. Deze twee voorbeelden geven exact hetzelfde resultaat...
Arco
Special Member
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Zo geeft delen door 3 veel meer code als delen door 2... 
(delen door een macht van 2 wordt door de compiler door een shift vervangen)
rew
four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
Op donderdag 14 november 2024 15:41:20 schreef blurp:
printf(x&1 ? "1": "0");
Dit geeft volgens mij op de nieuwste versies trouwens een waarschuwing. De compiler is niet zeker dat de eerste string naar printf geen van buiten af "beinvloedbare" dingen bevat.
printf("%c", x&1 ? '1': '0');
is wat dat betreft beter en... dan gaat ie vast weer WEL putchar aanroepen....
Op donderdag 14 november 2024 16:40:58 schreef rew:
[...]Dit geeft volgens mij op de nieuwste versies trouwens een waarschuwing. De compiler is niet zeker dat de eerste string naar printf geen van buiten af "beinvloedbare" dingen bevat.
Ik krijg geen waarschuwing met gcc 17.2. Ik snap ook niet waarom de compiler zou kunnen denken dat een unnamed string constante beinvloedbaar zou zijn. Hij heeft geen naam, dus kan niemand ooit aan dat adres refereren.
printf("%c", x&1 ? '1': '0');is wat dat betreft beter en... dan gaat ie vast weer WEL putchar aanroepen....
Nee, want de compiler (iedere versie) gaat dan klagen dat printf een string wil, en geen los karakter. En dat is een error, geen warning.
Ik had hem verkeerd overgenomen. Inderdaad gaat ie zo wel putchar gebruiken, en is de resulterende objectcode wel korter(40 ipv 43 bytes)
roadrunner84
Meep! Meep!
Op donderdag 14 november 2024 16:52:58 schreef blurp:
[...]Ik krijg geen waarschuwing met gcc 17.2. Ik snap ook niet waarom de compiler zou kunnen denken dat een unnamed string constante beinvloedbaar zou zijn. Hij heeft geen naam, dus kan niemand ooit aan dat adres refereren.
[...]
Nee, want de compiler (iedere versie) gaat dan klagen dat printf een string wil, en geen los karakter. En dat is een error, geen warning.
Lees hem nog eens? printf krijgt een string mee, namelijk "%c".
Toch, lijkt me dan
putch(x&1 ? '1': '0');beter.
Op donderdag 14 november 2024 15:01:25 schreef rew:
En ik verbaas me al jaren over mensen die denken dat als je het langer opschrijft het duidelijker wordt.
Ik denk dat je een goede kans hebt dat je niet de enige bent die jouw code moet begrijpen als is het maar dat je na een paar jaar (en soms veel sneller) je eigen code niet eens meer begrijpt. Je begrijpt mss wat iets doet, maar niet meer waarom dat ook al weer zo moest.
Op donderdag 14 november 2024 15:01:25 schreef rew:
Ik ben er op tegen om "teller" te schrijven. Iedereen weet dat de variabele i voor "actueel gebruik als teller in een loop" bedoeld is. Dan "teller" schrijven maakt de boel alleen maar onnodig langer en onoverzichtelijker.
Ik heb geen moeite met 'i', maar dan wel in loops die ik in één oogopslag kan zien. Bestrijken ze meer dan pakweg 10-15 regels, dan gebruik ik een langere naam om te weten waar deze var ook al weer voor diende. Misschien kun je het tijdens het schrijven nog wel allemaal in je hoofd houden, maar dat duurt ook maar een paar dagen. Blijkt er dan toch een bug ergens daar in de buurt te zitten, dan ben je veel langer aan het puzzelen. Met ook nog eens het risico dat je een nieuwe bug introduceert ipv plet.
Arco
Special Member
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Daarom heb ik me aangeleerd om korte begrijpelijke Engelse namen te gebruiken...
In het verleden veel code gemaakt voor buitenlandse klanten, daarvoor is 'teller' net zo onduidelijk als 'i' (nog afgezien van dat een teller in bijv. het Duits een bord is...
)
Engels worden alle programmeurs wel geacht te kunnen begrijpen.
Op donderdag 14 november 2024 14:30:16 schreef Hensz:
[...]
Ik verbaas me al meer dan 40 jaar over al die mensen die denken dat als je minder tekst gebruikt voor je source-code je dan ook compactere object-code krijgt.
Helemaal niet, ik prefix variabelen vaak met een n,d of sz om aan te geven dat het een integer,double of string (zero terminated is).
Waar ik me over verbaas is dat bij elke update van de compiler de code weer een stuk groter en trager is. In de jaren 80 had je nog wat concurrentie (Borland/Lattice/Oasys/Microsoft/Zortech) in de compilers zodat bij een compiler update je programma in een keer een stuk kleiner en sneller was. Maar dat waren dan wel optimized compilers voor een specifieke architectuur (zoals voor de MC68020)
Hoeben
Golden Member
https://www.hoeben.com https://www.overstockdevices.com https://www.asensor.eu https://www.circuitsonline.net/forum/user/4355#aanbod Voor alle verkoop: een tegenbod is altijd welkom!
Als we dan toch met mooie code bezig zijn, uit mijn oude PLM51 tijd, wel even goed data declareren (waar in sommige talen dan ook veel kracht ligt:
DECLARE xbits STRUCTURE ((BO, B1, B2, B3, B4, BS, B6, B7) BIT);
DECLARE x BYTE AT (.xbits);
dan kan dit:
if x(teller) = 0
then ...
else...
Erg leesbaar.
Arco
Special Member
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com