Ratlosigkeit mit char array



  • versuch mal bitte immer auf das vorletzte Zeichen zu schreiben( als mit dem Index 18 stat 19 !!!) und teste es bitte nochmal, ich bin fast der Meinung, dass es daran liegt!



  • nene, dann schreib ich ja wirklich in Stelle 18, und nicht in Stelle 19,
    und das sieht dann so aus:

    initialisiert:
    00000000000000000000
    Ausgabe 1 :
    00000000000000000010
    initialisiert:
    00000000000000000000
    Ausgabe 2 :
    000000000000000000101
    (Wert von currentValue: 49)
    (currentValue nach char gecasted: 1)

    Mit der Null-Terminierung haste wohl eher recht.

    Obwohl 'i' und 'currentValue' beide den Wert 49 haben, und auch
    (char)i und (char)currentValue beide den Wert '1' haben,
    scheint es einen Unterschied zu geben...



  • ich vermute mal das im Speicher die Variablen char[20] und direkt danach das currentValue sich befindet... und solange das currentValue == 0 ist, ist der String an dieser Stelle abgeschloßen! Wenn du jetzt currentValue auf 49 setzt, bekommst du die selbe Ausgabe, wie bei der ersten, nur ist diesmal stat der terminiertenden Null (beim ersten mal war es die vom currentValue) das currentValue == 49 und es wird damit die '1' ausgegeben (die zweite '1' in der zweiten Ausgabe) und dann kommt die terminierende Null!



  • #include <stdio.h>
    #include <sys/types.h>
    #include <wait.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    char count[20];
    int currentValue = 0;
    int value;
    
    int setValue(int i)
    {
       value = i;
       return (value);
    }
    
    int main(void)
    {
    
        int fill;
        for(fill = -19; fill >= 0; fill--)
        {
           count[fill] = '0';
        }
    
        printf("initialisiert: %s\n",count);   
    
        int i = 49;
        count[19] = (char) i;
        printf("Ausgabe 1    : %s\n",count);
    
        for(fill = 19; fill >= 0; fill--)
        {
           count[fill] = '0';
        }
    
        printf("initialisiert: %s\n",count);   
    
        currentValue = setValue(i);
        count[19] = (char) currentValue; 
        printf("Ausgabe 2    : %s\n",count);
    
        printf("(Wert von currentValue: %d)\n",currentValue);
        printf("(currentValue nach char gecasted: %c)\n",(char)currentValue);
    
        return (1);
    }
    


  • hdi schrieb:

    nene, dann schreib ich ja wirklich in Stelle 18, und nicht in Stelle 19,
    und das sieht dann so aus:

    initialisiert:
    00000000000000000000
    Ausgabe 1 :
    00000000000000000010
    initialisiert:
    00000000000000000000
    Ausgabe 2 :
    000000000000000000101
    (Wert von currentValue: 49)
    (currentValue nach char gecasted: 1)

    Mit der Null-Terminierung haste wohl eher recht.

    Obwohl 'i' und 'currentValue' beide den Wert 49 haben, und auch
    (char)i und (char)currentValue beide den Wert '1' haben,
    scheint es einen Unterschied zu geben...

    hast du wirklich überall die 19 erstetzt? insbesondere in den for schleifen!!!



  • okay, also wir sind der sache nun näher gekommen:
    Der Fehler passiert wohl im Aufruf der Funktion !

    Wenn ich mache:

    currentValue = 49;
    

    dann passt alles. (D.h. deine Theorie mit dem Speicher etc. stimmt hier nicht)

    aaber wenn ich mache:

    currentValue = setValue(i);
    

    DANN macht er diesen Schmarrn...

    Also, hier nochmal die Funktion:

    int setValue(int i){
    value = i;
    return value;}
    


  • Zeh Mau du machst den selben Fehler! Das letzt Byte im Sting muss für die terminierende Null bleiben, sonst kann der String nicht richtig angezeigt werden!



  • Bitte geht mal auf meinen Gedankengang ein:

    Es liegt wohl am Aufruf der Funktion!

    mit currentValue = 49; geht es doch wunderbar!

    ps @zeh mau:
    deine version macht den selben fehler (und zeigt ausgabe 1 übrigens gar nicht an, aber das is wohl eher ein flüchtigkeitsfehler)



  • bei mir funktioniert es, damit womit ich es (versucht hab) zu beschreiben^^

    #include <stdio.h>
    #include <sys/types.h>
    #include <wait.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    char count[20];
    int currentValue = 0;
    int value;
    
    int setValue(int i){
    
    value = i;
    
    return value;}
    
    int main(void){
    
            int fill = 18;    // auch hier 18 !
            for(; fill >= 0; fill--){count[fill] = '0';}
    
            printf("initialisiert: %s\n",count);
    
            int i = 49;
            count[18] = (char)i;
            printf("Ausgabe 1    : %s\n",count);
    
            fill = 18;    // auch hier 18 !
            for(; fill >= 0; fill--){count[fill] = '0';}
            printf("initialisiert: %s\n",count);
            currentValue = setValue(i);
            count[18] = (char)currentValue; printf("Ausgabe 2    : %s\n",count);
    
            printf("(Wert von currentValue: %d)\n",currentValue);
            printf("(currentValue nach char gecasted: %c)\n",(char)currentValue);
    
            return 1;
    }
    


  • hdi, glaub TLEP, und seine Theorie mit dem Speicher stimmt auch. Davon abgesehen sollte man count[19] auch wirklich noch mit '\0' (bzw 0) belegen.



  • in der tat geht es, jedoch ist dein array nur 19 zeichen lang..

    aber wenn ich ein array oben mit der Länge 20 initialisiere, will ich doch auch auf die Stelle 19 zugreifen können, also auf das letzte Zeichen.

    Damit hat man doch normalerweise auch keine Probleme oder?

    edit: also um nochmal den unterschied zu erfragen:

    wieso klappt alles ohne funktionsaufruf (currentValue = 49;) aber
    nicht mit dem aufruf: currentValue = setValue(i);

    Ich meine die Funktion setValue greift doch nirgends auf das array zu..

    Und deshalb halte ich die Theorie mit dem Speicher auch für nicht zutreffend.



  • wenn du 20 Zeichen haben willst, muss das Array halt char name[21] sein! Du musst IMMER wenn es sich um ein String handelt die Null mit einplanen, das MUSST du dir merken... es kommen die Verrücktesten Ausgaben wenn du das nicht beachtest! Nur wegen der einen '\0'.

    PS: Das 20. Zeichen muss nicht unbedingt initialisiert werden, da es eine globale Variabel ist, wird sie von Anfang an mit Null initialisiert, sonst nicht!



  • okay.. ich merk's mir 🙂

    habe aber noch immer nicht verstanden:

    currentValue = 49;

    geht wunderbar, auch wenn ich es so mache wie im ersten post, also alles mit 19 statt 18 usw..

    nur

    currentValue = setValue(i);

    geht nicht, wobei eben setValue() nicht im geringsten auf das array zugreift.

    D.h. ich verstehe nach wie vor nicht, wieso es hier Probleme mit dem Speicherzugriff oder Nullterminierungen gibt...



  • TLEP schrieb:

    es kommen die Verrücktesten Ausgaben wenn du das nicht beachtest! Nur wegen der einen '\0'.

    #include <stdio.h>
    
    char count[20];
    int value1 = 0;
    int value2 = 0;
    int value3 = 0;
    
    int main(void)
    {
    	for ( int i=19; i>=0; i-- )
    		count[i] = '0';
    	value1 = 1819043144;
    	value2 = 1867980911;
    	value3 = 6581362;
    	printf( "%s\n", count );
    	return 1;
    }
    

    :xmas1:

    Die 20 chars und die Integer-Variablen liegen im Speicher direkt hintereinander. Jedes char belegt 1 Byte, jedes int (bei mir) 4 Bytes. Wenn printf was ausgeben will, gehts von der Startadresse im Speicher los und gibt jedes Byte/Zeichen aus, bis es auf ein Null-Byte trifft. Meine Zahlen hab ich so gewählt, dass sie den ASCII-Code von sinnvollen Buchstaben enthalten. Ist recht einfach, wenn du weißt, wieviele Bytes ein Datentyp hat.
    Ein int hat (bei mir) 4 Bytes, also passen 4 ASCII-Zeichen rein. In value1 hab ich 'H' 'e' 'l' 'l' reingepackt. Da printf im char-Array kein Null-Byte findet, wandert es ja weiter im Speicher, direkt dahinter liegt halt value1. Also gibt es auch die Bytes von value1 aus, weil es nicht wissen kann, ob das jetzt nun eine Zahl ist oder sonstwas, es findet ja einfach nur Byte für Byte im Arbeitsspeicher vor.

    edit2: TLEP hats gut erklärt!



  • Das ist so:
    du deklarierst die Variablen

    char count[20];
    int currentValue = 0;
    int value;

    die werden mit Null initialisiert und stehen im Heap( oder zu deutsch Halde^^) so:

    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 0 ...
    | - - - char - array- - - - - - - - - - | |currentValue| ...
    

    nun schreibst du das komplette Array mit 48 (Zeichen '0'):

    48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 | 0 0 0 0...
    |---------char-array-------------------------------------------------------| |currentValue-| ...
    

    nun setzt du das 20. zeichen auf 49 und gibst die Sache aus. Diese Ausgeben funktioniert unter C so: es werden alle Zeichen auf dem Bildschirm ausgegeben bis ein 0 kommt! Es wird jetzt also folgendes gedruckt:

    48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 49 | 0 0 0 0

    entscheidend ist die 0 von dem currentValue Speicherbereich!

    bei der Zweiten Variante setzt du genau diesen Speicherbereich auch auf 49! Jetzt zur ausgabe: Dazu muss man wissen das ein int normaler Weise 32 Bit hat und auf den meinsten Architekturen als Big-Endian gespeichert werden ( das meist-signifikante Byte zuerst )
    sprich binär '49' ist dann

    00110001 00000000 00000000 00000000

    und jetzt steht im Speicher:
    48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 49 | 49 0 0 0

    und daher kommt die zweite '1', weil die 49 jetzt nochmal da drin steht!



  • @badestrand:

    was willst du damit sagen?
    Ich kann das Programm 100 mal ausführen, das Array ist immer sauber eine Kette von Nullen..

    Leute bitte lest euch doch mal aufmerksam durch, was ich sage :p

    Ich zweifel ja nicht daran, dass ihr es checkt, aber sorry, ich glaube nicht an eure Speicherprobleme und Nullterminierungsgeschichten...

    Nehmt den Code von meinem allerersten Post!

    Und ersetzt das currentValue = setValue(i) durch ein currentValue = 49;

    Ergebnis: Alles funktioniert wunderbar...

    Also bidde...Ich bin zwar Anfänger, aber wie erklärt ihr das?

    Es liegt, ich sage es nochmal, am aufruf der Funktion!



  • hdi.loggedout schrieb:

    @badestrand:

    was willst du damit sagen?
    Ich kann das Programm 100 mal ausführen, das Array ist immer sauber eine Kette von Nullen..

    Mist, bei mir hat's funktioniert! Was für'n Compiler hast du, und was für ein System?

    hdi schrieb:

    Also bidde...Ich bin zwar Anfänger, aber wie erklärt ihr das?

    Es liegt, ich sage es nochmal, am aufruf der Funktion!

    Hehe, es liegt indirekt an der Funktion, die Ursache findest du in TLEPs letztem Post.

    edit: Hab am obigen Code noch Kleinigkeit verändert, probiers noch mal 🙂



  • hmm...

    also ich halte noch dagegen 😛 ^^

    Er hat mir lediglich gezeigt (schön übrigens, danke :)), wie der Stack/Heap funktioniert.

    Aber nach seiner Theorie müsste auch:

    currentvalue = 49;

    den Fehler ausgeben, da das Array nicht null-terminiert ist.

    Das tut es aber nicht...

    Und die Funktion setValue(), falls sie indirekt, wie du sagtest, dafür verantwortlich ist... WO?

    Sie hat mit dem Array doch absolut goar nix am hut 🙂

    ps badestrand:
    auch diese funktion gibt schön die nullen aus 😉
    Jedoch ändere ich immer die for-schleife..
    int i = 19 kann mein compiler nicht in der schleifen direkt (outside C99-mode), ich deklariere int i = 19 davor und rufe dann die for-schleife einfach so auf:

    for (; i >= 0, i--)

    ...falls es deshalb nicht klappt ?



  • Das, wenn du die Funktion nicht aufrufst, alles klappt, ist Zufall!!! Wenn zufällig im Speicher danach keine Null stehen würde, wird es nicht mehr funktionieren, glaub uns! Die abschließende Null ist essenziell!!! Sorry mir ist es klar, das es daran liegt! Was muss ich machen um es die zu zeigen??



  • hdi schrieb:

    Und die Funktion setValue(), falls sie indirekt, wie du sagtest, dafür verantwortlich ist... WO?

    Sie hat mit dem Array doch absolut goar nix am hut 🙂

    Ja, aber wie TLEP schön dargestellt hat, ist currentValue erst 0 und stellt damit das Null-Byte, welches den String terminiert, später dann 49, wobei Byte-mäßig erst die 49 (also '1') und dann ein (bzw mehrere) Null-Byte kommt.

    Mach mal aus der Zeile currentValue = setValue(i); ein currentValue=6581362; . Ich wette, dann kommen die '0'en und dann "rld" 😉

    hdi schrieb:

    ps badestrand:
    auch diese funktion gibt schön die nullen aus 😉
    Jedoch ändere ich immer die for-schleife..
    int i = 19 kann mein compiler nicht in der schleifen direkt (outside C99-mode), ich deklariere int i = 19 davor und rufe dann die for-schleife einfach so auf:

    for (; i >= 0, i--)

    ...falls es deshalb nicht klappt ?

    Ne, daran dürfte es nicht liegen 😞 Was gibt denn bei dir sizeof(int) so aus?

    edit x: Wenn sizeof(int) bei dir auch 4 ist, was gibt denn
    printf( "%i %i %i %i\n", &count[0], &value1, &value2, &value3 ); bei dir aus? Interessiert mich einfach, warum das bei uns unterschiedlich läuft 🙂


Anmelden zum Antworten