- 3D-Druck Einstieg und Tipps         
Seite 2 von 2 ErsteErste 12
Ergebnis 11 bis 20 von 20

Thema: MAL Wieder "C" Frust

  1. #11
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    11.12.2007
    Ort
    weit weg von nahe Bonn
    Alter
    39
    Beiträge
    3.416
    Anzeige

    E-Bike
    weil es nicht prozessorspezifische alignment regeln beachtet (zumindest laut spezifikation) ... also bei nicht "packed" structs oder wenn du bit access machst könnte es gut passieren dass du irgendwo in eine lücke geschickt wirst oder hinter das struct guckst oder auf der stelle trittst
    es ist eben nicht "eindeutig"
    Es gibt 10 Sorten von Menschen: Die einen können binär zählen, die anderen
    nicht.

  2. #12
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Beiträge
    1.076
    Achso, ja, das packed hab ich drin:
    Code:
    /* the User preset range in the EEPROM was fixed to 16 Bytes */
    /* these paramters can changed by the user in normal operation mode */
    #pragma pack(1)  /* align the structure to bytes to minimize size */
    typedef struct 
    {
      U16  last_P10_pre;   /* last user Pressure for PRE-Insufflation */
      U16  last_Q10_pre;   /* last user Flow     for PRE-Insufflation */
      U16  last_P10_main;  /* last user Pressure for MAIN-Insufflation */
      U16  last_Q10_main;  /* last user Flow     for MAIN-Insufflation */
      BOOL last_Video;     /* last user Video on/Off state */
      U8   reserved1;
      U16  reserved2;
      U16  reserved3;
      U16  checksum;       /* CRC16 */    
    } t_user_data;
    #pragma pack()   /* end of packed structure */
    hier "dürfte" es also keine Lücken geben, der Compiler "sollte" es Byteweise ablegen.
    ohne das packed, wäre es gut möglich, dass er es auf die Standardbreite eines int aligned.

    Probier ich gleich mal....

    - - - Aktualisiert - - -

    ich hab das grad mal probiert:
    Code:
    //#pragma pack(1)  /* align the structure to bytes */
    typedef struct
    {
      short a;
      char  b;
      short c;
    } t_my_data;
    //#pragma pack()   /* end of packed structure */
    
    
    o = offsetof(t_my_data,c);
    jo, hier verschiebt sich der Offset um 1 Byte

    der Offset zu "c" ist unpacked = 4 bei packed = 3

    der GNU-ARM Compiler macht das als richtig.
    Geändert von Siro (23.11.2018 um 11:19 Uhr)

  3. #13
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    11.12.2007
    Ort
    weit weg von nahe Bonn
    Alter
    39
    Beiträge
    3.416
    fast alle machen das richtig, aber es ist halt nciht "spezifiziert" ... es KÖNNTE ja sei dass man IRGENDWANN mal einen exotischen compiler verwenden KÖNNTE der EVENTUELL ..... mehr sarkasmus und das forum erleidet einen schlaganfall, drum brech ich das mal ab XD
    Es gibt 10 Sorten von Menschen: Die einen können binär zählen, die anderen
    nicht.

  4. #14
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Beiträge
    1.076
    das steht ja in meiner Softwaredokumentation welcher Compiler verwendet wird...

    Juti, sind wa durch, ich wünsche alleseits ein schönes Wochenende.

    Habe wieder etwas dazu gelernt, mit dem MACRO: mir gefällt es

    Siro

  5. #15
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    11.12.2007
    Ort
    weit weg von nahe Bonn
    Alter
    39
    Beiträge
    3.416
    kann mal ein kleines abstrakt davon hier einstellen, cih finde es ziemlich nützlich und relativ kompakt ist es auch (bis es sich entfaltet .... origami issn scheiß dagegen )
    Es gibt 10 Sorten von Menschen: Die einen können binär zählen, die anderen
    nicht.

  6. #16
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Beiträge
    1.076
    @Ceos: ja stell mal rein....

    Ich "tratsche mal noch ein bissle"

    Zum Thema Codetest statisch oder wie auch immer: wie Aussagekräftig ist das eigentlich ?

    Ich hatte 15 Jahre lang den gleichen "funktionierenden" Code für die RS232 verwendet.
    Der lief auf meinen PICs und auf auch dem PC mit INTEL 80xx
    bis ich dann auf ARM umgestiegen bin, plötzlich traten merkwürdige Fehler auf:

    Das beschreibt recht gut wie wenig Aussagekräftig ein Test, ja sogar ein Unittest sein kann, wenn er nicht direkt auf dem Zielsystem (Prozessor) ausgeführt wird.
    Der Comiler hat seine Aufgabe richtig getan, aber die Systemarchitektur macht einem plötzlich einen Strich durch die Rechnung:

    Wer lange Weile hat (is ja Wochenende) kann sich das gerne mal anschauen, was ich damals ermittelt habe:

    Ein Zeichen aus dem Empfangspuffer holen:

    Code:
    U8 uart_getc(void)
    { U8 value;
      if (rx_count)
      {
        value = rx_buffer[rx_out];
        if (++rx_out >= UART_RX_BUFFER_SIZE) rx_out = 0;
        rx_count--;
      }
      return value;
    }
    dazu muss man wissen, was der Compiler für einen Assembler Code generiert hat: aus rx_count-- wird beim LPC1768 (ARM Code)

    LDR r0,[r2, #0x14] ; lade r0 mit dem Wert rx_count
    SUBS r0,r0,#1 ; ziehe von r0 eins ab
    STR r0,[r2,'0x014] ; speicher den Wert an rx_count

    Nehmen wir an, rx_count steht auf 1. Nun gelangen wir in den Assemblercode 2.te Zeile. im r0 Register befindet sich dann der Wert 1. In dem Moment tritt ein Receive Interrupt auf. Die Software verzweigt sofort zur Interrupt Service Routine.
    Dort steht folgender Code:

    Code:
    void uart_isr(void)
    {
      rx_buffer[rx_in]=databyte;
      if (++rx_in >= UART_RX_BUFFER_SIZE) rx_in = 0;
      rx_count++;
    }
    rx_count wird also am Ende der Interrupt Routine um 1 erhöht.
    jetzt kehrt die Software zurück zur Routine uart_getc.
    zur Info: rx_count stand auf 1 und wurde im Interrupt nun auf 2 erhöht. Im Register r0 steht aber noch der Wert 1, dieser wurde ja zuvor in der funktion uart_getc geladen. Nun zieht die Software in uart_getc eins ab. im r0 register steht nun 0. Dieser Wert wird dann zurück an die Speicherstelle rx_count geschrieben. Das wars es schon, alles durcheinander. Es befindet sich ein neues Zeichen im Puffer und rx_count steht auf 0.

    Damit dies nun nicht mehr passiert, werden vor dem Verändern der variablen rx_count alle Interrupts gesperrt. Im Prinzip bräuchte man nur den RX Interrupt sperren. Dann wird der vollständige Code
    rx_count-- in jedem Fall ausgeführt. Danach werden die Interrupts
    wieder eingeschaltet.

    Selbiges Problem tritt auch beim TX Interrupt auf.
    Auch hier werden vor dem Verändern der Variablen tx_count alle Interrupts gesperrt.

    Bei einem PIC zum Beispiel tritt dieses Problem normalerweise nicht auf, da er ein pre oder post increment direkt in einem Befehl ausführt, da kann also keiner "dazwischen" funken.
    Darauf sollte man sich aber auch hier nicht verlassen, wer weis schon was der C-Compiler daraus macht.

    Je nach verwendeten Prozessor kann es also funktionieren oder auch nicht. Wenn der Prozessor zum Beispiel einen 2 Assembler Befehl erzeugt, wäre auch kein Problem vorhanden: Beispiel:

    hier kann das mov R0,@rx_count ; lade R0 Register mit der Adresse von rx_count
    inc [R0] ; erhöhe die Speicherstelle worauf R0 zeigt

    auch hier kein Promlem, weil das indirekte increment nicht unterbrochen werden kann.
    da es in einem Befehl ausgeführt wird.

    Bei einem Intel Prozessor passiert dies auch nicht, auch hier wird das increment in einer einzigen Anweisung ausgeführt. Sonst wäre der Fehler auch schon in meinen PC-Programmen vor 15 Jahren aufgetreten.

    Code:
    LEA EDI,dword ptr rx_count
    inc dword ptr ES:[EDI]
    Eine statische Codenalyse oder was auch immer für ein Testprogramm hätte diesen Fehler wohl nie aufdecken können.
    Fazit: "atomarer code" war gestern, das geht kaum noch..

    Heutztage bekomme ich teilweise nichtmal ein einziges BIT mehr gesetzt ohne das der Code nicht unterbrochen werden könnte.
    Da werden teilwesie 5 Zeilen Assemblercode draus gebildet obwohl ich nur ein Bit setzten möchte.

    Ich liebe aber solche Fehler, daran könnte ich mich ewig dran aufhalten.
    Kein Witz, sowas dann zu finden macht mir echt Spass. Besser also DOKU

    ----- P A U S E --
    Schön fand ich auch, wo der C-Compiler mir Codezeilen weggelöscht hat, die ER für unnötig hielt:
    Beim UART muss man das sogenennt DLAB Bit setzen um auf spezielle Register zuzugreifen,
    das gab es schon in 90 Jahren so und es wurde tatsächlich in die modernen 32 Bitter übernommen.
    Also setzte ich das Bit
    dann meine Baudrate
    und setze das Bit zurück

    Der Compiler fragt sich: Wozu soll das gut sein, Du benutzt es doch garnicht und schmeist genau diese beiden Zeilen raus....
    Das hat und hätte ein Pascal Compiler nie getan.

    Natürlich kann und muss man dann gegensteuern. Ich brauche "volatile" und dann gehts.
    Aber hier ist mir der Compiler manchmal zu selbständig. Man kann solche Optimierungen auch leider nicht abstellen.

    Was sagt da die Code Anaylse dazu ? solche Fehler können doch garnicht erkannt werden ?
    Zumal die der Compiler ja erst reinbaut...Das lief ja, bis er eigenmächtig Änderungen vorgenommen hat

    Diese moderne, angebliche Intelligenz ist nicht immer wünschenswert.....
    Geändert von Siro (25.11.2018 um 07:14 Uhr)

  7. #17
    Erfahrener Benutzer Roboter Genie Avatar von White_Fox
    Registriert seit
    04.10.2011
    Beiträge
    1.473
    Was bin ich froh, Hardware zu machen...

    (Naja, stimmt nicht ganz, bei meinem letzten Job war ich im Wesentlichen auch nur mit Programmiererei beschäftigt, und was hab ich da über Visio C und Visual Studio geflucht, diese elenden Scheißkonstrukte...)

  8. #18
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    11.12.2007
    Ort
    weit weg von nahe Bonn
    Alter
    39
    Beiträge
    3.416
    wie Aussagekräftig ist das eigentlich ?
    ziemlich, es kommt auf das Tool an und die Regeln die darin festgelegt werden ob und welche Fehler man findet .... für dich wäre es zum Beispiel extreeeeem hilfreich gewesen, wenn du eine REgel definiert hättest die Warnungen für alle Variablen generiert die innerhalb des statischen und des ISR Code verwendet werden und NICHT "volatile" deklariert wurden.

    Du hast das perfekte Beispiel gezeigt wie man Variablen nicht verwenden sollte. Die Count Variable sowohl im statischen als auch im ISR Code zu manipulieren ist gefährlich.
    Ich benutze für derartige Zwecke üblicherweile (ich nenn sie mal so) "Katz und Maus" Variablen und bau mir damit einen Ringpuffer. Die Maus ist der ISR counter der sich immer weiter erhöht und defineirt oder implizit überläuft (wenn man den Luxus von genug Speicher hat). Die Katze ist dann mein Readmarker, der immer der Maus hinterher läuft. So kann ich immer und zu jederzeit sicherstellen dass nur ein "Prozess" (streng genommen ist das multithreading) eine Variable zu einer bestimmten Zeit bearbeiten kann und ichkann sogar zu jedem Zeitpunkt eine Plausibilitätsprüfung machen.

    Ausnahme dabei ist natürlich wenn du Variablen hast die aufeinander zulaufen, dann musst du tatsächlich volatile machen damit du garantiert den aktuellen Wert erhälst oder eben manuell die ISRs blockieren bis die Plausibilitätsprüfung abgeschlossen ist.

    Das Makro das ich versprochen habe kommt im Laufe des Tages wenn cih es mal kurz funktionell arrangiert habe

    - - - Aktualisiert - - -

    So, hier ist das versprochene Makro, man muss zwar noch ein wenig improvisieren damit es auch sofort funktioniert aber der code wie er ist kann als template benutzt werden, man muss nur seine Datenstrukturen einbauen und den switch case entweder in eine art "callViaEnum(myEnum_t what)" methode dafür einbauen oder gleich direkt im code einarbeiten

    Code:
    //die Kontruktionsliste, hier werden alle Daten eingegeben um das Programm zu konstruieren
    
    #define XTABLE(ENTRY) \
    //            ENUM    |    METHODE      |                             DATA                           (ACHTUNG, dieser Kommentar erzeugt ein Multiline Comment Warning und dient nur als Tabellenkopf)\
    ENTRY(   CALL1,          callMethode1,        {irgend_welche_daten, in_struct, oder_array, oder_einzeln)\
    ENTRY(   CALL2,          callMethode2,        {irgend_welche_daten, in_struct, oder_array, oder_einzeln)\
    ENTRY(   DO_STH,        callSomething,       {irgend_welche_daten, in_struct, oder_array, oder_einzeln)
    
    
    //ein X-Makro um uns passend die notwendigen Daten bereit zu stellen
    
    #define AS_DATA(ENUM,METHODE,DATA) DATA
    
    //das X-Makro um den Caller Switch-Case zu erzeugen, benötigt das DATA Makro, deswegen die Reihenfolge beachten
    
    #define AS_METHODE_CASES(ENUM,METHODE,DATA) \
       case(ENUM):\
       {\
          parameter = prepareSomething(DATA);\
          METHODE(parameter,irgendwasanderes);\
          break;\
       }
    
    //hier erzeugen wir einen Enum anhand unserer Tabelle als Lookup und Call Referenz für den switch-case
    
    #define AS_ENUM(ENUM,METHODE,DATA) ENUM,
    
    typedef enum
    {
       XTABLE(AS_ENUM)
           LAST_ENTRY
    }entryEnum_t;
    
    
    //wir erzeugen hier Beispielsweise auch eine LookupTable mit den Daten falls wir dynamisch darauf zugreifen müssen 
    //und hinterlegen sie implizit/explizit im ROM (static const, oder andere prefixe je nach compiler) zum RAM sparen
    
    typedef struct
    {
           entryEnum_t entryEnum;
           somedata_t entryData;
    }lookupDataStruct_t;
    
    static const lookupDataStruct_t entryDataLookup[] = {
           XTABLE(AS_DATA)
    };
    
    
    //hier generieren wir die eigentlichen Prototypen
    
    #define AS_PROTOTYPE(ENUM,METHODE,DATA) return_t METHODE(simpledata_t input_parameter, otherdata_t andere_sachen);
    XTABLE(AS_PROTOTYPE)
    
    
    //irgendwo im Code erzeugen wir dann an der passenden stelle den switch-case
    
    switch(entryEnum)
    {
           XTABLE(AS_METHODE_CASES)
           default:
           {
                 ASSERT(FAIL);
                 break;
           }
    }
    Jedes Tool sollte in der Lage sein die Makros aufzulösen und über den switch-case eine code coverage von 100% damit erreichen
    wenn ich nur Functionpointer in einer Tabelle einsetze kommt die Linkerebene dazwischen, man kann es zwar logisch auflösen aber das beherrscht kaum ein Tool, da die wenigsten auch den konkreten Inhalt von Arrays in die Analyse mit einbeziehen.

    Was dieses X-Makro erzeugt ist ein sauber lesbarer Switch Case der Anhand der Enums die Daten passend verarbeite udn der Methode dann die Parameter übergibt und sie aufruft.

    Wer Tippfehler findet darf sie behalten :P
    Geändert von Ceos (26.11.2018 um 12:58 Uhr)
    Es gibt 10 Sorten von Menschen: Die einen können binär zählen, die anderen
    nicht.

  9. #19
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Beiträge
    1.076
    Hallo CEOS,
    für mein count Problem habe ich jetzt auch einen anderen Weg genommen,
    scheinbar ähnlich deiner Beschreibung.
    Ich habe jetzt getrennte Einlese und Auslesezeiger.
    Der Empfangs RX-Interrupt benutzt nur "seinen" Einlesezeiger.
    Das Hauptprogramm seinen "Auslesezeiger"
    Hier kann man nun, um die Anzahl Bytes im RX Puffer zu ermitteln,
    ohne Probleme beide Werte voneinander abziehen.
    Es spielt nun auch keine Rolle mehr ob es indexe in das Array sind
    oder direkt Zeiger auf die entsprechende Pufferpositionen.

    rx_count = abs(inPtr-outPtr) // oder auch umgekehrt.

    Ein Problem könnte aber immer noch auftauchen,
    bei 8 Bit Controllern, wenn er Low und High Byte bei Zugriffen separat tätigt.
    also:

    inc(LowByte); wenn LowByte = 0 dann inc(HighByte)

    Microchip PIC-Code:
    incfz rx_count+0 // increment low byte of count, scip next Line if Zeroflag is set
    incf rx_count+1 // else increment also the High Byte of count

    Eine wasserdichte Software zu schreiben ist eine echte Herausforderung.....
    Interrupts sperren mag ich eigentlich überhaupt nicht, ist aber manchmal unumgänglich.
    -----
    Zu deinem Konstrukt:
    Ui, da muss ich erstmal durchblicken....ich analysiere aber noch.
    Im Prinzip habe ich es, glaube ich zumindest, verstanden um was es geht.
    Bei Dir bildet sich die case Schleife selbständig indem Du die obige Struktur erweiterst.

    Etwas ähnliches (ist aber doch um einiges anders) habe ich in meinem Setupmenü gemacht.

    Code:
    /* every menu point has the following structure */
    typedef struct
    {
      U16 menu_no;             /* displayed menu no */
      U8  flags;               /* 3 flags for User, Service, Internal Setupmode */
      S16 min;                 /* min value of parameter for range check */
      S16 max;                 /* max value of parameter for range check */
      U8  led_code[3];         /* 3 Digit LED Information Text, only 2 digits used */
      U8  lcd_code[20];        /* 20 Digit LCD Information Text, not used at time */
      void (*MenuFunc)();      /* call this function if menu point want to change */
      void (*OnChangeFunc)();  /* maybe call a special function if param changed */
      } TMenuPoint;
    
    /* here is the complete initialized Setup Menu */
    const TMenuPoint menu[]={
    { 1,   /* Key Beep Volume Frontpanel Buttons */
      F_USER + F_SERVICE + F_INTERNAL,
      BEEP_MIN_VOL,BEEP_MAX_VOL,
      {SEG_CODE_b,SEG_CODE_0,0},       /* displaycode "b0" */
      "Key Beep            ",
      Setup_VolumeKeyBeep,
      OnChangeBeeper
      },
      
      { 2,   /* Overpressure Beep Volume */
      F_USER + F_SERVICE + F_INTERNAL,
      BEEP_MIN_VOL,BEEP_MAX_VOL,
      {SEG_CODE_b,SEG_CODE_1,0},        /* displaycode "b1" */
      "Overpressure Beep   ",
      Setup_VolumeOverpressureBeep,
      OnChangeBeeper
      },
      
    .......
    Mein Code ist doch was ganz anderes, stelle ich grad fest, ist auch kaum statisch zu analysieren denke ich...

    Ich habe mit Macros noch nicht viel gemacht in "C" hier kann man sich doch Einiges vereinfachen wie ich deinem Code entnehme.
    Im PIC Assembler habe ich aber derart viele Macros geschrieben, das es später schon fast wie ein Hochsprache aussah.

    Mit Code coverage usw. habe ich auch noch nichts zu tun gehabt. Machst Du solche Tests mit "Tessy" ? oder welche Tools benutzt Du dafür ?



    Siro
    Geändert von Siro (26.11.2018 um 14:39 Uhr)

  10. #20
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Beiträge
    1.076
    Ich lese grade über "statische" Codeanalyse und da tauchte folgender Text auf:

    Problematiken in "C"
    Das wären unter anderem die undefinierte Auswertungsreihenfolge bei arithmetischen Ausdrücken,
    compilerabhängige Ergebnisse beim Rechts-Shift von negativen ganzen Zahlen und die undefinierte Bitbreite des Datentyps int.
    Nun bin ich doch etwas verunsichert:
    Ich benutze ja sehr gerne mal das Shiften in alle Richtungen, zumindest links und rechts...

    Das stellt ja ein "erhebliches" Risiko dar, wenn nicht eindeutig festgelegt ist, was der Compiler daraus macht.
    Ist natürlich auch etwas problematisch mit dem shiften und abhängig vom Datentyp, wer mal Assembler programmiert hat
    weis um die Problematik des Vorzeichenbits. Hier gibt es teilweise unterschiedliche Befehle zum Schieben,
    die das Vorzeichen beachten, auffüllen, rotieren usw.

    Kann man sich bei "C" darauf verlassen, dass ein Schieben mit "unsigned" immer richtig funktioniert ?
    Einen signed, egal welchen Typs, würde ich eh nicht shiften wollen, da das Ergbenis ungewiss...

    Durch die "Integer promotion" wird ja generell erstmal alles zum int gecastet und der hat ein Vorzeichen,
    Aber selbst diese Aussage stimmt in "C" ja nicht weil:
    Bei Bitdefinitionen ist es wiederum compiler spezifisch festgelegt bzw. einstellbar ob es ein signed oder unsigned ist.
    Der C-Compiler von IAR Embedded Workbench z.B. interpretiert einen "int" bei Bitdefinitionen vorzeichenlos,
    also wie ein "unsigned int" Möchte man eine Bitkombination mit Vorzeichen haben, muss man explizit einen "signed int" benutzen,
    was ursprünglich ja der default int wäre(war, ist ?) oder wie auch immer...
    Somit gehört in meinen Augen ein "int" als VERBOTEN, da dieser Typ nicht festgelegt ist.
    Das habe ich auch schon seit Jahren in meiner Doku entsprechend spezifiziert und benutze ihn auch nicht.
    Ein int könnte demnach Alles sein was mindestens 16 Bit hat. Mehr sagt es anscheinend nicht aus.

    Na wie dem auch sei, je mehr ich mich mit der C Programmierung beschäftige, umso mehr erkenne ich wie schwierig es ist,
    Fehler zu vermeiden. Eine "sinnvolle" statische Codeanalyse erscheint mir auch nicht wirklich sinnvoll, denn
    ich müste dem Tool ja erstmal die ganzen "Eigenheiten" meines verwendeten Compilers verraten.

    Ich glaube ich kann eure Gedanken lesen
    Der Siro meckert nur immer....
    Das ist aber nicht so, das sieht nur so aus...
    ich beschäftige mich doch recht intensiv mit der Programmierung den Sprachen und deren Eigenheiten
    um halt bessere Software zu schreiben, also versteht es bitte nicht falsch.
    Ich schöpfe ja auch immer wieder viele neu Informationen von euch und das ist gut so.

    Siro

Seite 2 von 2 ErsteErste 12

Ähnliche Themen

  1. " DiBaDu und Dein Verein" für Hackerspace Bremen 2017 - wieder dabei !
    Von Andree-HB im Forum Offtopic und Community Tratsch
    Antworten: 67
    Letzter Beitrag: 08.11.2017, 07:46
  2. Mal wieder eine "fast" funktionierende Stoppuhr
    Von Unregistriert im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 2
    Letzter Beitrag: 09.08.2016, 09:53
  3. Genfer Autosalon 2016 - "Knutschkugel" Isetta kommt wieder - als Elektroauto
    Von Roboternetz-News im Forum Neuigkeiten / Technik-News / Nachrichten / Aktuelles
    Antworten: 0
    Letzter Beitrag: 02.03.2016, 13:30
  4. Versteckte Ordner wieder "unversteckt" machen
    Von Sebas im Forum PC-, Pocket PC, Tablet PC, Smartphone oder Notebook
    Antworten: 2
    Letzter Beitrag: 20.09.2011, 16:19
  5. "Make all" schon wieder Probleme
    Von Spongebob85 im Forum C - Programmierung (GCC u.a.)
    Antworten: 6
    Letzter Beitrag: 08.08.2007, 21:06

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

12V Akku bauen