Hallo Besucher, der Thread wurde 59k mal aufgerufen und enthält 114 Antworten

letzter Beitrag von daybyter am

skoe erzählt C in 14 Tagen

  • So, da liegt das Teil. Darin enthalten ist ein größtenteils neues Vorwort und "Abend 1"


    http://skoe.de/wiki/doku.php?id=ckurs:start


    Diesen Thread habe ich als Diskussionsfred verlinkt. Es wäre interessant, wer das überhaupt liest und ob es noch weitere Unzulänglichkeiten als das "int des Anstoßes" gibt. Also meldet Euch bitte hier. Das mit dem int habe ich dort übrigens geändert.

  • skoe:
    da hat sich ja das aufbleiben gelohnt : )


    ich poste mal hier die pn an skoe, von den oben im thread die rede ist:


    -----
    änder bitte "void main()" in "int main(void)", damits von anfang an richtig gemacht wird


    -----
    soweit ich weiss, wird im standart auch ein quellcode akzeptiert, wo in "main" ein return fehlt, obwohl als rückgabetyp von main "int" angegeben wurde.


    -----
    ich habe nochmal genauer recherchiert ; )


    die möglichkeit das "return" weglassen zu können, ist wohl erst mit c99 eingeführt worden. kann man auch mit gcc ausprobieren, wenn man mit und ohne "-std=c99" übersetzt.


    im iso standart steht dazu:


    Zitat

    5.1.2.2.3 Program termination


    (...) reaching the } that terminates the main function returns a value of 0.


    wie manches andere wurde das wohl auch von c++ übernommen. im stroustrup kann man nämlich lesen:


    Zitat

    The minimal C++ program is


    Code
    1. int main() { }


    (...) The int value returned by main(), if any, is the program’s return value to "the system." If no value is returned, the system will receive a value indicating successful completion.


    das pendant in c ist dann:


    Code
    1. int main(void) { }


    aber in jedem fall ist nur ein "int" vor "main" standartkonform.

  • ogd: Ich hatte Dir ja geschrieben, dass ich das später mit aufnehmen werde. In dem Hello-World-Programm habe ich das "return 0" explizit hingeschrieben, weil ich noch nicht ausprobiert habe, welche Compiler diesen Aspekt von C99 schon implementieren. Ich hau den cc65 bei Gelegenheit mal an und prüfe das.


    Teil 2 soll übrigens behandeln:
    1. Funktionen, Parameter, Rückgabewerte (noch keine variablen Parameter-Listen)
    2. Einfache Variablen mit ganzzahligen Typen (u.a. für die Parameter in Punkt 1)
    3. Funktionsprototypen


    Teil 3 dann vielleicht:
    1. Die Teile der Toolchain (präprozessor, compiler, assembler, linker)
    2. Header-Files und Bibliotheken
    3. Kleine Beispielprogramme und was der Compiler draus macht (z.B. Vergleich hello world mit puts und printf)


    Klingt das sinnvoll?

  • Wenn du auch mal über die cfg-Dateien berichten kannst für den cc65 , wäre sehr wichtig.
    Denn darin ist für den c64 und Plus4 zb die Speicheraufteilung festgelegt. Die verstehe ich auch noch nicht.


    Wenn man damit umgehen kann, erstart man sich glaube ich ein bisschen ärger mit dem Speicher bzw unerklärliches Verhalten vom cc65.


    mfg

  • In dem Hello-World-Programm habe ich das "return 0" explizit hingeschrieben, weil ich noch nicht ausprobiert habe, welche Compiler diesen Aspekt von C99 schon implementieren. Ich hau den cc65 bei Gelegenheit mal an und prüfe das.


    ja, cc65 schluckt das ohne zu murren:


    Code
    1. int main(void) {}



    Teil 2 soll übrigens behandeln:
    1. Funktionen, Parameter, Rückgabewerte (noch keine variablen Parameter-Listen)
    2. Einfache Variablen mit ganzzahligen Typen (u.a. für die Parameter in Punkt 1)
    3. Funktionsprototypen


    ich würde "einfache variablen ...." vorziehen, da die funktionsparameter typisiert werden müssen



    Teil 3 dann vielleicht:
    1. Die Teile der Toolchain (präprozessor, compiler, assembler, linker)
    2. Header-Files und Bibliotheken
    3. Kleine Beispielprogramme und was der Compiler draus macht (z.B. Vergleich hello world mit puts und printf)


    wann behandelst du denn die ersten kontrollanweisugen?

  • Wenn du auch mal über die cfg-Dateien berichten kannst


    Klar, Linkerscripts sind wichtig, besonders für unsere Systeme. Kommt auch dran. Aber bevor wir was an die richtige Stelle linken können, müssen wir erstmal ein Programm schreiben können ;-)


    > wann behandelst du denn die ersten kontrollanweisugen?
    Stimmt, finde ich eigentlich auch wichtiger als die Themen die dort bei Tag 2 stehen.


    Vielleicht sollte ich den Compiler noch ein paar Tage als Black Box behandeln? Mal sehen.


    > ja, cc65 schluckt das ohne zu murren:
    Okay, danke. Dann nehme ich die Zeile da wieder raus, dann ist es wieder etwas minimalistischer.

  • korrektur zu "Abend 1 - Installation des C-Compilers - Unter Windows - Variante 2: Variablen nur wenn benötigt"


    die von mir vorgeschlagene cmd-datei funzt in dieser form nur, wenn man sie im installationsverzeichnus aufruft. "%~dp0" wird nämlich durch den aktuellen pfad ersetzt. mit dem vorteil, dass man das installationsverzeichnis beliebig verschieben kann, ohne an "init.cmd" etwas ändern zu müssen.


    wenn man allerdings von jedem beliebigen ort aus den compiler in das system einbinden will, sollte die "init.cmd" in einem path-verzeichnis (wie etwa c:\windows) liegen und so ausschauen:


    Code
    1. set CC65_LIB=<pfad>\lib
    2. set CC65_INC=<pfad>\include
    3. path <pfad>;%path%


    dabei ist <pfad> jeweils durch das installationsverzeichnis zu ersetzen, im vorgegebenem beispiel durch "e:\cc65"

  • void main()


    Gibt beim cc65 keine Warnmeldung mehr. Warum bei der "main" hier im cc65 eine Rückgabe erwartet werden soll ist mir nicht plausibel. In der Beschreibung vom cc65 steht auch, das der cc65 nicht ganz c-konform ist , weil doch einige wichtige Grundsätzliche c-dinge fehlen wie für die Pc-Programme. Auch die Variablen sind nicht alle vorhanden usw. Man muss schauen, was man damit auf eine 8Bit-maschine machen kann . Zb Volatile gibt es auch nicht, obwohl es doch eine gewisse stabilität gibt für Variablen, ohne das man überrascht wird wenn man es nicht benutzt. Darum ist die Überwachung hier beim cc65 durch den Programmierer bestimmt.


    mfg

  • Jaja, ich bin immernoch hier. Ärgere mich gerade damit rum, dass ein wxWidgets-Programm unter Windows was anderes macht als unter Linux. Aber das ist eine andere Baustelle. Wenigstens ist es erklärbar.


    ogd: Ach so, hatte angenommen, dass %~dp0 den Pfad der Datei angibt, in dem das Skript liegt. Wenn dem nicht so ist, trage ich am besten dort den absoluten Pfad ein. Kenne mich mit den Variablen unter Windows gar nicht aus.


    @schnucke: Ich kann Deine Zweifel verstehen. Hier haben die anderen aber prinzipiell recht. Es nutzt Dir nicht wirklich was, wenn Du es im cc65 richtig machst, aber es schadet auch nichts. Wozu das mit dem int (auf anderen Betriebsystemen) gut ist, erklär ich in einer der nächsten Folgen. Und mit einem haben die Leute hier recht: Wenn man es von Anfang an richtig macht, tritt man später nicht in Tretminen.

  • ich habe noch eine option in cc65 entdeckt ; )


    Code
    1. --standard std Language standard (c89, c99, cc65)


    wenn man


    Code
    1. void main(void) {}


    mit "cl65 --standard c89 test.c" oder "cl65 --standard c99 test.c" übersetzt, kommt doch eine fehlermeldung:


    Code
    1. test.c(1): Error: `main' must always return an int


    der compiler benutzt also "--standard cc65" (als voreinstellung) beim übersetzen. und ist somit tolleranter.

  • der compiler benutzt also "--standard cc65" (als voreinstellung) beim übersetzen. und ist somit tolleranter.


    Du kannst den cc65 nicht mit dem Standart-c89 vergleichen, weil der cc65 zuviele Hohlräume hat speziell für den 8-Bitter. Dazu ist er zu unvollkommen. Wenn man in dem cc65 zb noch die Float reinbrigen würde, würde dieses garnicht mehr auf die Standart-8Bitter vom Speicher her passen und von der Geschwindigkeit ganz zu schweigen.


    Also vergesst die Standartisierung für den c64 nach dem Motto: es gibt nur ein wahres "c".
    Man kann das gut an den ASM-Routinen erkennen, womit der cc65 hergestellt worden ist, es ist ein schöner Kompromiss.


    Wichtig ist das dieses anpasste "c" für diesen kleinen Computer schnell ist, verständlich ist , compakten Code erzeugt und funktionell ist. Wenn er das nicht wäre, könnte ich auch einen schönen Basic-compiler nehmen.
    Und das erfüllt der cc65 hervorragend.


    Diese wird auch in der Beschreibung vom cc65 erwähnt.


    Also die Suppe nicht so heiss essen, wie man diese vorgesetzt bekommt, abkühlen lassen. :bia


    mfg

  • Also vergesst die Standartisierung für den c64 nach dem Motto: es gibt nur ein wahres "c".


    Da muss ich energisch widersprechen!


    Selbstverständlich habe ich Verständnis für 8 Bit Einschränkungen und dem fehlenden float. Aber da wo es um Konventionen und Definitionen geht, bin sehr dafür dassdie exakt eingehalten werden. Noch dazu wo es keinerlei Nachteile hat wenn man die exakt einhält!!


    Es geht da nicht nur ums Prinzip sondern auch um Portabilität!

  • Also, für mich sind die Abweichungen belanglos und kann auch gut damit abends schlafen gehen.
    So Geil bin ich nicht auf Perfektion. Kann eigentlich so weiter gemacht werden wie bisher. Die Programme laufen bei mir wie gewünscht.


    Und den Kursus, wie er jetzt geschrieben ist für den cc65 , finde ich Klasse.
    Also nach dem Motto: Kanten müssen sein, warum alles Rund schleifen. :winke:


    mfg

  • Es geht da nicht nur ums Prinzip sondern auch um Portabilität!


    Das geht so nicht beim cc65, weil ich vor dem Compilieren den Computertyp angeben muss (atari,c64,plus4 usw) und auch schon den Speicherbelegungsplan(cfg) mitgebe.
    Das verschiedene Speichergemurkse der 8Bitter wo ich welchen Platz für freie Variablen, String , Bitmapspeicher, Farbspeicher usw habe/ausnutze geben kein einheitliches Bild. Jedes Byte Zählt.
    Und es werden eine ganze menge Poke/Peeks benutzt und andere Eigenheiten die so "c" nicht kennt.


    Daran denken : Es ist kein 3Ghz Rechner mit 1GByte Speicher usw.


    Und ich gebe auf den 8Bitter nicht nur "hallo welt" aus.


    mfg

  • >Du kannst den cc65 nicht mit dem Standart-c89 vergleichen,
    >weil der cc65 zuviele Hohlräume hat speziell für den 8-Bitter.
    >Dazu ist er zu unvollkommen.


    Wenn man sich immer mehr mit dem cc65 beschäftigt und z.B. den Beitrag von ogd oben liest, kommt man eher zu einem anderen Schluss: Der cc65 ist verblüffend nah an den Standards.


    >Wenn man in dem cc65 zb noch die Float reinbrigen würde,
    >würde dieses garnicht mehr auf die Standart-8Bitter vom Speicher her
    >passen und von der Geschwindigkeit ganz zu schweigen.


    Auch das stimmt so nicht ganz. Es ist ermutlich eher eine Aufwandssache. Nur durch das Vorhandensein einer float-Unterstützung werden die Programme gar nicht und der Compiler nicht merklich langsamer (das mit dem Compiler kann uns sowieso egal sein, der läuft ja auf einem PC. Der Grund: Die Funktionen, die mit den Floats rumhantieren, würden nur dann in ein Programm gelinkt werden, wenn sie dort tatsächlich benutzt werden.


    Ein paar Ausnahmen gibt es: Funktionen, die dann mit float umgehen können müssten, weil sie potentiell damit aufgerufen werden könnten, würden größer werden. Das ohnehin dinosaurierartige printf würde dann vermutlich noch ein paar hundert bytes größer werden. Aber auch dafür würde sich sicher eine Lösung finden lassen, z.B. "--disable-float" und zwei Bibliotheksversionen.


    Hab übrigens Deinen Post oben wg. puts vs. printf gesehen, mich aber noch nicht dazu geäußert, weil ich das Thema in der nächsten Lektion angehen will.


    Zum thema "volatile": Wenn ich jetzt nichts übersehe, ist beim cc65 sowieso jede Variable "volatile", weil er sie nicht dauerhaft in Registern aufbewahrt. Deshalb hat das Schlüsselwort keinen Effekt - ohne den Standard zu verletzen.


    Das Argument mit dem portierbaren Code von Diddl stimmt aber: Dadurch, dass Du nur einen Schalter umsetzen brauchst, um ein Programm für den Plus4, C64, NES etc. zu erzeugen, ist der Code ja portabel. Kannst Du das nicht mehr, ist er es nicht. Die Programme im Kurs kannst Du (bis demnächst) auch mit MS Visual Studio, GNU C oder sonstwas übersetzen. Ein Linkerscript ist auch ein Mittel zu diesem Zweck - es entfernt nämlich die Systemabhängigkeit aus dem eigentlichen Programm.


    Danke für das Lob für den Kurs. Wenn er tatsächlich gelesen wird, mach ich weiter.

  • Die Programme laufen bei mir wie gewünscht.


    deine postings hier im forum beweisen aber das gegenteil ; )


    EDIT:

    Zum thema "volatile": Wenn ich jetzt nichts übersehe, ist beim cc65 sowieso jede Variable "volatile", weil er sie nicht dauerhaft in Registern aufbewahrt. Deshalb hat das Schlüsselwort keinen Effekt - ohne den Standard zu verletzen.


    dazu passend aus der cc65-mailingliste: http://www.cc65.org/mailarchive/2002-04/1243.html

  • ... und der einzige grund dafür das der cc65 keine floats unterstützt ist das noch keiner die passende runtime library dazu geschrieben hat :) auf lange sicht wird sich das sicher ändern.


    Bevor man sich diese Arbeit macht muss man auch nach die Sinnhaftigkeit fragen. Bzw. ob die entstehenden Code Größe dann noch Spass macht bzw. überhaupt noch Applikationen erlaubt.


    Beim Atmel AVR gibt es float optional. Das macht aber auch nur für größere Controller mit 128KB Flash (Atmega128) Sinn.

  • die frage der sinnhaftigkeit stellt sich in dem fall nicht wirklich - das fernziel von cc65 ist irgendwann man ein standardkonformer kompiler zu sein, und dazu gehört auch float unterstützung :) das man das ganze dann optional macht und im regelfall warscheinlich nichtmal nutzt steht auf nem ganz andren blatt =)


    so wahnsinnig viel codegrösse macht das davon ab garnicht aus, im c64 (bzw dessen basicrom) steckt ja schon eine komplette floating point bibliothek, die man auch benutzen kann. (und wie der zufall will bastel ich grad an einem derartigen wrapper.... mal guckn wann der so weit ist das ich den mal posten kann)