Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info
edit: Uitleg: const waardes zijn bekend wanneer je bestand gecompileerd wordt en kunnen in de datatabel van je applicatie worden opgeslagen. Dat kan later direct worden opgevraagd. Wat je nu doet is het kopieren vanuit de tabel omdat je een aanpasbare char* t hebt in plaats van een constante. Overigens moet het char[] *t zijn?
[ Voor 85% gewijzigd door Sebazzz op 30-06-2010 17:30 ]
[Te koop: 3D printers] [Website] Agile tools: [Return: retrospectives] [Pokertime: planning poker]
Verwijderd
Als je namelijk direct een variable sprintf't hoeft er niks in het geheugen opgeslagen te worden
ik kan me vergissen
Dat zou een array van strings zijn.
'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.
Zelfs als ik die regel waar ik de variabele in zet laat staan in mijn code dan nog gebruikt die tweede situatie meer geheugen.Verwijderd schreef op woensdag 30 juni 2010 @ 17:32:
Ik ben niet ervaren in C, maar je declareert in je nieuwe situatie een char pointer naar een stuk geheugen waar je "S%04d" in opslaat. Dan zal dit waarschijnlijk die 128 bytes verklaren.
Als je namelijk direct een variable sprintf't hoeft er niks in het geheugen opgeslagen te worden
ik kan me vergissen
Ik snap het verschil niet, in beide gevallen geef ik een pointer mee aan die functie. In het ene geval staat het in het programmageheugen. Die pointer t wijst ook naar het programmageheugen, die string blijft een constante.
Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info
Uhm, een array van characters toch? En dus een C-style string.
http://www.cprogramming.com/tutorial/lesson9.html
Je declareert het niet als constante en de compiler optimaliseert het dus niet. Je *t kan je op ieder gewenst moment aanpassen.Ik snap het verschil niet, in beide gevallen geef ik een pointer mee aan die functie. In het ene geval staat het in het programmageheugen. Die pointer t wijst ook naar het programmageheugen, die string blijft een constante.
[ Voor 40% gewijzigd door Sebazzz op 30-06-2010 18:13 ]
[Te koop: 3D printers] [Website] Agile tools: [Return: retrospectives] [Pokertime: planning poker]
Verder lijkt me dat Sebazzz idd gelijk heeft, al klopt dat niet helemaal met wat C hoort te doen. Iets als char * t = "hoi" is eigenlijk sowieso fout. Het betekent niet dat je t dan aan mag passen, want die wijst nog altijd naar een const char *, alleen wordt dat (een const string literal aan een non-const char pointer assignen) expliciet toegestaan in de standaard. Als je 'm aan wilt kunnen passen dan moet je [] gebruiken, niet *.
[ Voor 134% gewijzigd door .oisyn op 30-06-2010 18:24 ]
Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.
1
| const rom char *t = "S%04d"; |
Developer Accused Of Unreadable Code Refuses To Comment
In ieder geval heb ik wel vreemdere dingen gezien, en ik zou me er persoonlijk niet zo druk om maken.
edit:
Maar misschien hebben Sebazz en Icelus gelijk en implementeert je compiler de C standaard niet goed. Dan zou 'ie dus de string in writable memory alloceren omdat je 'm aan een char* toekent. Maar dan nog lijkt me dat het verschil in geheugengebruik 'm alleen zit in sections die anders gepad worden. Nog steeds niet echt iets om je zorgen om te maken.
[ Voor 23% gewijzigd door Soultaker op 30-06-2010 18:37 ]
.oisyn schreef op woensdag 30 juni 2010 @ 18:19:
Als je 'm aan wilt kunnen passen dan moet je [] gebruiken, niet *.

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.
Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.
Een ander onderscheid is dat de char t[] array in z'n geheel op de stack van de functie wordt gezet. Je kunt dit mooi zien als je een char t[] aanmaakt in een recursieve functie: elke keer dat de functie zichzelf aanroept zie je de pointerwaarde van t omlaag zakken. Daarentegen zal een char *t bij elke recursieve aanroep nogsteeds naar hetzelfde stukje geheugen wijzen..oisyn schreef op woensdag 30 juni 2010 @ 21:42:
Alleen als functieparameters. char *t is een pointer, char t[] is een array. Die laatste mag dan ook alleen als je 'm direct initaliseert, want de grootte van de array moet af te leiden zijn uit de initialisatie. Of hij moet extern zijn. In het geval van char t[] = "hallo" is t dus gewoon een char\[6].
"Logica brengt je van A naar B, verbeelding brengt je overal." - Albert Einstein
Ik maak me er druk om omdat ik nu een heap van 4K groot heb (hoe groter hoe beter, want ik heb redelijk wat dynamisch geheugen nodig), en mijn stack minimaal 512 bytes moet blijven. Door dit geintje is mijn stack ineens 430 bytes groot geworden. Maar goed, ik heb nog links en rechts wat optimalisaties te doen.Soultaker schreef op woensdag 30 juni 2010 @ 18:34:
In ieder geval heb ik wel vreemdere dingen gezien, en ik zou me er persoonlijk niet zo druk om maken.
Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info
Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.
Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info
Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.
Ok, maar dan moet je de gegenereerde object files eens in detail bekijken zodat je kunt zien waar de ruimte heen gaat (nu, en voor de wijziging). Nu zie je alleen het totaal en daaruit kun je de oorzaak niet afleiden.Grijze Vos schreef op donderdag 01 juli 2010 @ 01:06:
Ik maak me er druk om omdat ik nu een heap van 4K groot heb (hoe groter hoe beter, want ik heb redelijk wat dynamisch geheugen nodig), en mijn stack minimaal 512 bytes moet blijven.
Ik vermoed dat er nu een extra sectie gegenereert wordt ofzoiets. Op zichzelf lijkt me dat nog steeds geen ramp, behalve als je die ~100 bytes echt nodig hebt. Dan kun je misschien de compileropties nog tweaken om bijvoorbeeld de alignment van secties te tweaken, of alle data secties te mergen (een aparte read-only sectie is voor embedded development niet altijd nodig).
Ik neem aan dat je programma sowieso vrij kort is, anders zal je zo een meervoud van 100 bytes kwijt zijn puur aan code.
[ Voor 51% gewijzigd door Soultaker op 01-07-2010 02:24 ]
Inderdaad..oisyn schreef op donderdag 01 juli 2010 @ 01:53:
Dus de formatstring die je aan sprintf() geeft moet aanpasbaar zijn?
Er wordt inderdaad een extra sectie gegenereerd, wat ik me afvraag is waarom. Ik weet niet of dat kan met dit apparaat. Ben niet zo bekend met de hardware, en een deel van de code is precompiled meegeleverd door een andere partij, daar heb ik ook niet echt invloed op.Soultaker schreef op donderdag 01 juli 2010 @ 02:20:
[...]
Ok, maar dan moet je de gegenereerde object files eens in detail bekijken zodat je kunt zien waar de ruimte heen gaat (nu, en voor de wijziging). Nu zie je alleen het totaal en daaruit kun je de oorzaak niet afleiden.
Ik vermoed dat er nu een extra sectie gegenereert wordt ofzoiets. Op zichzelf lijkt me dat nog steeds geen ramp, behalve als je die ~100 bytes echt nodig hebt. Dan kun je misschien de compileropties nog tweaken om bijvoorbeeld de alignment van secties te tweaken, of alle data secties te mergen (een aparte read-only sectie is voor embedded development niet altijd nodig).
Mwoah, het gaat om een interpreter zodat er software geprogrammeerd kan worden met een simpele DSL, omdat met handmatige C code het programmageheugen snel vol zat. Nu blijkt het datageheugen ook een probleem te zijn op sommige punten. Qua programmageheugen zit ik nog prima (75% in gebruik van de 128K), maar het datageheugen is problematisch: 11.5K in gebruik door het gedeelte dat de third party heeft gebouwd, +-512 bytes voor de stack, en 4K voor de heap, waarbij ik zoveel mogelijk wil opslokken als mogelijk is voor de heap.Ik neem aan dat je programma sowieso vrij kort is, anders zal je zo een meervoud van 100 bytes kwijt zijn puur aan code.
[ Voor 81% gewijzigd door Grijze Vos op 01-07-2010 10:10 ]
Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info
Als Sebazzz en Icelus suggesties niet helpen helpt dit misschien:
1
| char format[] = "S%04d"; |
Of desnoods zo (onder de aanname van een 32-bit big-endian architectuur):
1
2
3
4
| int temp[2]; temp[0] = 0x53253034; temp[1] = 0x64000000; char *format = (char*)temp; |
Als dat niet in de code sectie terecht komt weet ik 't ook niet meer.
[ Voor 66% gewijzigd door Grijze Vos op 01-07-2010 10:23 ]
Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info
Hoezo niet goed? De C standaard staat een heleboel toe. Functies in writeable memory zetten? Zelfs dat is volkomen legitiem. Immutable strings in ROM zetten is een niet-verplichte optimalisatie.Soultaker schreef op woensdag 30 juni 2010 @ 18:34:
edit:
Maar misschien hebben Sebazz en Icelus gelijk en implementeert je compiler de C standaard niet goed. Dan zou 'ie dus de string in writable memory alloceren omdat je 'm aan een char* toekent.
Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein
[ Voor 3% gewijzigd door .oisyn op 01-07-2010 12:45 ]
Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.
Weet niet welke compiler gebruikt wordt maar Microchips compiler zet strings standaard in ROM. Vandaar dat beiden niet zijn aan te passen. (Heb voornamelijk met de 8-bit PIC18 gewerkt. Misschien dat de 32-bit PIC3x anders is)..oisyn schreef op donderdag 01 juli 2010 @ 12:45:
Wat raar is is dat er een verschil zit tussen const char * str = "hoi" en char * str = "hoi". In beide gevallen mag je 'm niet aanpassen, ookal is die tweede non-const.
[ Voor 9% gewijzigd door Icelus op 01-07-2010 13:09 ]
Developer Accused Of Unreadable Code Refuses To Comment
Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.
Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.
Ok, daar heb je technisch gelijk in, ik neem het terug.MSalters schreef op donderdag 01 juli 2010 @ 10:23:
Hoezo niet goed? De C standaard staat een heleboel toe. Functies in writeable memory zetten? Zelfs dat is volkomen legitiem. Immutable strings in ROM zetten is een niet-verplichte optimalisatie.
Het punt was dat de compiler string literals die aan een char* worden toegekend op een andere manier alloceert dan wanneer ze aan een const char* worden toegekend, waarvoor in de C standaard geen enkele aanleiding te vinden is. Dat is ook het punt dat .oisyn (herhaaldelijk) maakt. Maar je hebt gelijk dat de C standaard dit gedrag niet verbiedt.
Het is in dit geval wel vervelend omdat het blijkbaar tot meer overhead leidt terwijl daar (voor standaard C programma's) geen noodzaak toe was.
Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.
Dan vergelijk je de asm sources en weet je waardoor het precies komt.
En anders compileer je die 2 proggies en gooi je ze door een disassembler /debugger , kom je er ook wel.
If you choose to criticise you choose your enemies
Hum, van de 16k neemt dit stuk 11.5K in? Valt daar niet wat te winnen?...11.5K in gebruik door het gedeelte dat de third party heeft gebouwd...
Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.
Het is bij alle embedded compilers (en zeker die van chip fabrikanten) het waard om de manual is goed door te nemen aangezien deze compilers vaak ook op enkele (of veel) vlakken van de C standaard afwijken. Waarschijnlijk staat er wel iets in over met welke modifier je kan bepalen waar in welk geheugen en/of welke sectie je string komt te staan. Als je dan toch aan het lezen bent bekijk dan ook je linker manual en de inhoud van je linker script voor het zelfde geld maakt ie daar nu gewoon een sectie met wat extra ruimte die die eerst weg optimaliseerde.
[ Voor 8% gewijzigd door jmzeeman op 01-07-2010 22:55 ]
Daarentegen, als de formatstring direct aan sprintf wordt meegegeven, kan de compiler daar veel meer mee... Zo geeft GCC bijvoorbeeld al waarschuwingen als het aantal of type argumenten niet overeenkomen. Maar in het geval van de oude situatie is ook het argument constant en is het eindresultaat van de formatstring tijdens het compileren al bekend. Ik sta er niet van te kijken als de gegenereerde code in feite een strcpy doet van "S0100". Het zou dan in elk geval niet de enige/eerste compiler zijn die dat optimaliseert... Weer andere (embedded) compiler "zien" dat je alleen de code voor het evalueren van %04d nodig hebt, dat scheelt dan dus ook weer de nodige code.
offtopic: Nooit gedacht dat ik nog iets toe te voegen had, waarbij .oisyn, MSalters en NMe me niet al voor waren...
[ Voor 7% gewijzigd door Elijan9 op 03-07-2010 12:17 . Reden: typo ]
War is when the young and stupid are tricked by the old and bitter into killing each other. - Niko Bellic
Heb je de topic dan überhaupt wel doorgelezen? Want:Elijan9 schreef op zaterdag 03 juli 2010 @ 12:03:
offtopic: Nooit gedacht dat ik nog iets toe te voegen had, waarbij .oisyn, MSalters en NMe me niet al voor waren...
Volgens mij heb ik nu al 4x gezegd dat je een string literal sowieso nooit mag aanpassen, ook al assign je 'm aan een non-const pointer. Dit resulteert dus in undefined behaviour:Het grote verschil tussen de oude en nieuwe code, is dat de compiler er nu veel minder mee kan... "t" wijst naar een format string, maar t kan veranderen en naar een andere format string gaan wijzen...
1
2
3
4
5
| void foo() { char * t = "Hallo"; t[0] = 'P'; } |
En 't' zelf mag je natuurlijk sowieso aanpassen, ookal is het een const char *. Het is namelijk geen char * const of const char * const.
Dit is natuurlijk wel correct
1
2
3
4
5
| void foo() { char t[] = "Hallo"; t[0] = 'P'; } |
Maar dan kun je 't' weer niet naar een andere buffer laten wijzen.
[ Voor 40% gewijzigd door .oisyn op 04-07-2010 00:39 ]
Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.
Volgens mij mis jij de strekking van mijn verhaal. De string literal mag je niet aanpassen, maar de t mag je wel naar een andere string literal laten wijzen. Daarom weet de compiler niet stellig op het moment van de sprintf dat de formatstring hier altijd "S%04d" zal zijn en dus kan de compiler hier onmogelijk een strcpy van maken van "S0100"..oisyn schreef op zondag 04 juli 2010 @ 00:38:
Heb je de topic dan überhaupt wel doorgelezen? Want:
[...]
Volgens mij heb ik nu al 4x gezegd dat je een string literal sowieso nooit mag aanpassen, ook al assign je 'm aan een non-const pointer.
War is when the young and stupid are tricked by the old and bitter into killing each other. - Niko Bellic
Die optimalisatie gebeurd iig niet. De 100 in mijn voorbeeld is een simplificatie. In de echte code is dit een variabele.Elijan9 schreef op zondag 04 juli 2010 @ 14:58:
[...]
Volgens mij mis jij de strekking van mijn verhaal. De string literal mag je niet aanpassen, maar de t mag je wel naar een andere string literal laten wijzen. Daarom weet de compiler niet stellig op het moment van de sprintf dat de formatstring hier altijd "S%04d" zal zijn en dus kan de compiler hier onmogelijk een strcpy van maken van "S0100".
Ik denk dat dit het is. En dat hun implementatie(s) van sprintf een buffer in het statisch geheugen gebruiken. En om de twee implementaties ieder hun eigen buffer ofzo.jmzeeman schreef op donderdag 01 juli 2010 @ 22:43:
Welke compiler gebruik je? De Microchip MPLAB C compiler heeft iig aardig wat eigenaardigheden. De DSC pics zijn voor mij even geleden maar ik meen dat rom pointers een ander type zijn als data pointers en dat deze ook anders benaderd worden en niet aan elkaar assignable zijn (of was dat alleen bij de 18f PICs?). Een string die in een gewone char * moet kan dan dus niet in program memory staan omdat je compiler dan niet zou weten welke instructies die moet gebruiken om de data te laden. Ook hebben de string functies overloads voor data en rom strings, het kan maar zo zijn dat er een overload die eerst niet gebruikt werdt nu wel wordt gebruikt met extra geheugen gebruik tot gevolg (maar dat zou alleen voor je program memory moeten gelden).
Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info