wieder mit dem Zeiger



  • Hallo,
    Habe wieder ein Problem mit Zeiger.

    int main()
    {
    int i;
    char zeiger = NULL;
    zeiger = (char )malloc(5sizeof(char));
    zeiger = (char
    )F();
    for(i = 0; i < 5; i++)
    {
    printf("%d\n", *(zeiger + i));
    }
    }

    char *F()
    {
    char a[5] = {1, 2, 3, 4, 5};
    return a;
    }

    Mit dem Prog. ist NUR die erste Zahl richtig!
    Warum?
    Danke im Voraus



  • benutz mal bitte Code-Tags das nächste mal!

    zeiger = (char *)malloc(5*sizeof(char));
    

    1. Du sollst nicht den Rückgabewert von malloc Casten!
    2. sizeof(char) ist immer 1 und somit überflüssig

    zeiger = (char*)F();
    

    1. Du brauchst den Rückgabewert von F() nicht Casten, da dieser char * ist, dein Compiler warnt dich vielleicht, da du F() nicht vor dem benutzen deklariert hast und dieser nach C89 von int ausgeht. Du solltest aber lieber F() deklarieren, da du sonst auf Architekturen, wo sizeof(int) != sizeof(void*) ist Probleme bekommen kannst.
    2. Du hast Speicher alloziert, gibst den aber nicht frei und veränderst den Pointer!

    char a[5] = {1, 2, 3, 4, 5};
    return a;
    

    Du gibst einen Zeiger auf ein lokales Array zurück, wenn du es ausserhalb der Funktion benutzen willst, ist das Array schon längst zerstört und es tritt undefiniertes Verhalten auf. Außerdem kannst du für Zahlen doch viel besser Integer nutzen

    Das Programm in der überarbeiteten Version

    #include <stdio.h>
    #include <stdlib.h>
    void F(int *);
    
    int main(void)
    {
      int *array=malloc(5*sizeof(int));
      int i=0;
      if(array==NULL)
        return 1;
      F(array);
      for(;i<5;++i)
        printf("%d\n",array[i]);
      free(array);
      return 0;
    }
    
    void F(int *array)
    {
      array={1, 2, 3, 4, 5};
    }
    


  • Hi,
    @puff,
    es tut mit leid, aber auch dein versuch funktioniert nicht!!!

    Ein generischer Zeiger (void) muss immer !! gecastet werden, sónst gibt es
    zurecht Fehlermeldungen
    Auch die Initialisierung deines Arrays ist falsch!!

    Mach es dann doch bitte schon so:

    #include <stdio.h>
    #include <stdlib.h>
    void F(int *);
    
    int main(void)
    {
      int *array=(int*)malloc(5*sizeof(int));
      int i=0;
      if(array==NULL)
        return 1;
      F(array);
      for(;i<5;++i)
        printf("%d\n",array[i]);
      free(array);
      getchar();
      return 0;
    }
    
    void F(int *array)
    {
      int i;
      for (i=0;i<5;i++)
      array[i] =i+1;
    }
    


  • Original erstellt von <francais>:
    ...
    Ein generischer Zeiger (void) muss immer !! gecastet werden, sónst gibt es
    zurecht Fehlermeldungen
    ...

    hmmmm .... Du solltest
    a) in Deinem C Buch nochmal das Kapitel über Zeiger lesen und/oder
    b) das C Buch, in dem das empfohlen wurde verbrennen!

    In C kann es "gefährlich" sein, wenn man einen void*-Zeiger castet!!! king hat das bereits erklärt - siehe auch: diesen Beitrag.

    [ Dieser Beitrag wurde am 03.01.2003 um 14:28 Uhr von mady editiert. ]



  • hi,

    @mady,
    rede doch nicht solchen Unsinn!

    Dann lass doch mal das (int*) weg und compiliere einmal
    int *array =malloc(5*sizeof(int));
    mit
    a) Microsoft-Compiler
    b) DEV-C++ -Compiler

    und einmal mit dem (int*)

    und lass bitte deine undifferenzierten Äußerungen sein!!

    MfG

    pierre



  • Bist du dem Link in madys Beitrag mal gefolgt?



  • @MFK,

    meinst du, ich hätte die <stdlib.h> nicht eingebunden???

    MFG
    pierre



  • Nachtrag:

    Ein kurzer Kommentar aus www.cplusplus.com

    Return Value.
    A pointer to the allocated space.
    The type of this pointer is void*. A type cast to the desired type of data pointer should be performed on this returned pointer in order to be used as an ordinary array of a concrete type.
    If the system could not allocate the requested block of memory or if the size requested was 0 a NULL pointer is returned.

    MfG
    pierre



  • Der Quelltext kompiliert ohne Probleme, mit einem C Compiler.

    KA wie oft ich das jetzt schon erklärt habe... Also:

    1. In C++ wird ein cast benötigt, weil in der Sprache C++ viele implizierte Typumwandlungen abgeschafft wurden. Wenn Du obigen Code mit einem C++ Compiler kompilierst, dann gibt das i.d.R einen Fehler.
    2. In C werden void*-Zeiger implizit umgewandelt. Es wird kein cast benötigt. Aus K&R II:

    Zeiger auf void

    Jeder Zeiger auf ein Objekt darf in den Typ void * umgewandelt werden, ohne daß Informationen verloren gehen. Wenn das Resultat zurück in den ursprünglichen Zeigertyp umgewandelt wird, wird der ursprüngliche Zeigerwert wiederhergestellt. ...

    Das bedeutet jetzt auch, daß void* Zeiger eine _andere Größe_ oder _eine andere interne Repräsentation_ haben können, als andere Datentypen. Und es bedeutet, dass mein Compiler diese Umwandlung vornehmen darf.

    Also: Das Problem ergibt sich, wenn entsprechende include-Anweisungen vergessen wurden, und eine Funktion (malloc) aufgerufen wird, die einen void*-Zeiger liefert. Nachdem aber der Prototyp dieser Funktion nicht bekannt ist, wird ein passender Prototyp angenommen - der Funktionsaufruf liefert die passenden Parameter, als Rückgabewert wird dann int angenommen. Wenn der cast fehlt, gibt's eine Warnung vom Compiler, dass ein int in einen Zeiger gewandelt wird. Damit bekomme ich einen Hinweis auf einen Fehler.

    Wenn ich einen cast verwende, bekomme ich diesen Hinweis nicht!

    Soviel zu meiner "undifferenzierten Äußerungen" ....

    Pfff



  • Und noch eins:

    aus www.dinkumware.com
    The values stored in the object are indeterminate. You can
    safely convert the return value to an object pointer of any type whose size is not greater than size.

    Reicht das als Nachweis?

    MfG
    pierre



  • Original erstellt von <francais>:
    Reicht das als Nachweis?

    Wofür? Dass ein void* gecastet werden muss, wie Du behauptet hast? Oder dafür, dass du das Problem des Castens des von malloc zurückgegebenen Zeigers in C noch immer nicht verstanden hast?

    Letzteres.



  • hi,

    @MFK,@mady,
    die Wahrheit liegt wie immer in der Mitte.

    ad1) Wer benutzt heute schon reine C-Compiler, wenn dann doch zum überwiegenden
    Teil C++-Compiler.

    ad2) Ihr wollt doch nicht obige Referenzen in Frage stellen oder???
    ad 3) Die überwiegende Literatur schlägt vor, aus Sicherheitsgründen ein
    casten zu verwenden.
    Dies meine ich mit einer "differenzierten" bzw. "undifferenzierten" Aussage.

    Bei einem "modernen" (C++-)Compiler gibt es nur Fehlermeldungen, wenn man das
    Casten vergessen hat.

    MfG
    pierre



  • Original erstellt von <francais>:
    **hi,

    @MFK,@mady,
    die Wahrheit liegt wie immer in der Mitte.

    ad1) Wer benutzt heute schon reine C-Compiler, wenn dann doch zum überwiegenden
    Teil C++-Compiler.

    ad2) Ihr wollt doch nicht obige Referenzen in Frage stellen oder???
    ad 3) Die überwiegende Literatur schlägt vor, aus Sicherheitsgründen ein
    casten zu verwenden.
    Dies meine ich mit einer "differenzierten" bzw. "undifferenzierten" Aussage.

    Bei einem "modernen" (C++-)Compiler gibt es nur Fehlermeldungen, wenn man das
    Casten vergessen hat.

    MfG
    pierre**

    Hallo pierre!

    Ich benutze vorwiegend C Compiler. Es gibt noch sehr viele Umgebungen, von ausschließlich C Compiler eingesetzt werden.

    Einen cast kann ich verantworten, wenn
    - Ein C Programm einmal nach C++ portiert werden soll.
    - Der Programmierer genau weiß, was ein cast ist und was er bedeutet!!

    Vielleicht kannst Du mir ein paar Beispiele für 'Literatur' geben in welcher der cast empfohlen wird. Das deckt sich nämliche nicht mit meiner Erfahrung. Die meisten (eigentlich alle) Bücher, die ich in den letzten 10 Jahren zu C gelesen habe und die den cast aus anderen Gründen als die gerade Aufgeführten empfehlen, sind Müll und es ist schade um das Papier, auf dem sie gedruckt sind.

    Natürlich stelle ich die dinkumware-lib-Beschreibung nicht in Frage. Aber ich kann eine Aussage wie 'ein cast ist notwendig' nicht unterstützen. Eigentlich alle C-Experten die ich kenne oder von denen ich Beiträge gelesen habe, verurteilen den cast eines void*-Zeigers ausdrücklich. Ausnahmen habe ich aufgeführt.



  • ups: Nochwas.

    Bei einem "modernen" (C++-)Compiler gibt es nur Fehlermeldungen, wenn man das
    Casten vergessen hat.

    Die meisten modernen C-Compiler geben keine Warnung, wenn der cast nicht "vergessen", und der passende Prototyp aber nicht gefunden wurde.

    [ Dieser Beitrag wurde am 03.01.2003 um 16:02 Uhr von mady editiert. ]



  • Original erstellt von <francais>:
    **hi,

    @MFK,@mady,
    die Wahrheit liegt wie immer in der Mitte.
    **

    in diesem Fall nicht.

    Der einzige Grund warum man einen void* casten kann ist der, dass man C++ kompatibilitaet waren will - aber dann sollte man gleich C++ verwenden!!

    ad1) Wer benutzt heute schon reine C-Compiler, wenn dann doch zum überwiegenden
    Teil C++-Compiler.

    Warum sollte man C mit einem C++ COmpiler verwenden??
    C COmpiler werden zB sehr stark bei mikroprozessoren verwendet - da macht C++ komischerweise keinen Stich.

    ad2) Ihr wollt doch nicht obige Referenzen in Frage stellen oder???

    Ich hoere lieber auf comp.lang.c.moderated und de.comp.lang.c sowie dem K&R

    DAS sind Referenzen auf die man sich verlassen kann - nicht irgendwelche Webseiten.

    Ausserdem sagt Dinkumware nix von casten!

    ad 3) Die überwiegende Literatur schlägt vor, aus Sicherheitsgründen ein
    casten zu verwenden.

    Ja, die meisten Buecher empfehlen auch die conio.h zu benutzen und sagen void main() sei legal und fflush(stdin) flusht stdin.

    Lehrbuecher sind KEINE Referenz!

    Bei einem "modernen" (C++-)Compiler gibt es nur Fehlermeldungen, wenn man das
    Casten vergessen hat.

    Dann bekommst du aber eine am Deckel - malloc in einem C++ Programm - shame on you!

    Bsp:

    int main(void)
    {
      char* p=(char*)malloc(100);
      free(p);
      return 0;
    }
    

    Und leider leider leider, fuehrt dies zu einem Absturz und du kommst und kommst nicht drauf warum...

    laesst man den cast weg - sieht man den fehler und alles ist inordnung!



  • hi,

    wer hat denn gesagt, dass ich malloc() in einem C++-Programm verwende??
    Du kannst aber toll zwischen den zeilen lesen! Du solltest Politiker werden!

    Nein, mal im Ernst. Ich habe nur von einem C++-Compiler gesprochen und dass
    diese in den meisten Schulen und Universitäten verwendet werden.

    Erklär mir doch bitte, bei welchem Compiler dein Programm zu einem Absturz
    führt??

    MfG
    pierre



  • Original erstellt von mady:
    In C++ wird ein cast benötigt, weil in der Sprache C++ viele implizierte Typumwandlungen abgeschafft wurden.

    Welche außer der hier angeführten meinst Du? Ich hätte gesagt, dass das Typenkonzept das gleiche ist, von der bewusst in C eingeführten 'Lücke' abgesehen.

    Vielleicht kannst Du mir ein paar Beispiele für 'Literatur' geben in welcher der cast empfohlen wird.

    Im K&R2 wird er konsequent verwendet ...

    Original erstellt von <francais>:
    Wer benutzt heute schon reine C-Compiler, wenn dann doch zum überwiegenden Teil C++-Compiler.

    Viele (Unix-) Systeme bringen erst mal nur einen C-Compiler mit. Wenn ein C++-Compiler mitgeliefert wird, dann ist er unbrauchbar, weil uralt. Und mal ganz davon abgesehen ist mein C-Compiler _wesentlich_ schneller bei der Übersetztung von C-Programmen, als der C++-Compiler. Kein Wunder, denn die C++-Programmiersprache ist ungleich komplexer als C.



  • Original erstellt von <francais>:
    **hi,

    wer hat denn gesagt, dass ich malloc() in einem C++-Programm verwende??
    Du kannst aber toll zwischen den zeilen lesen! Du solltest Politiker werden!
    **

    Du hast gesagt, dass sich ein C++ Compiler beschwert wenn man nicht castet.
    Darauf habe ich gemeint, wenn du malloc in einem C++ Programm verwendest, bist du selber schuld.
    Denn mit einem C++ COmpiler kann man halt kein C Programmieren.

    Nein, mal im Ernst. Ich habe nur von einem C++-Compiler gesprochen und dass
    diese in den meisten Schulen und Universitäten verwendet werden.

    Ja und? Quasi jeder C++ COmpiler hat auch einen C Modus!
    Entweder C++ ODER C - ein mischding ist kaese.

    Erklär mir doch bitte, bei welchem Compiler dein Programm zu einem Absturz
    führt??

    Auf allen Plattformen wo sizeof int != sizeof char*
    zugegeben - unter windows hast du keine Probleme, aber wenn du irgendwann mal die Plattform wechsest, oder jemand ein Programm von dir portiert - dann kanns nen crash geben, den man nur sehr schwer finden kann!

    und was sind die Vorteile vom casten?



  • Original erstellt von <francais>:
    **...
    Nein, mal im Ernst. Ich habe nur von einem C++-Compiler gesprochen und dass
    diese in den meisten Schulen und Universitäten verwendet werden.

    Erklär mir doch bitte, bei welchem Compiler dein Programm zu einem Absturz
    führt??
    ...**

    Tja ... nur leider heißt dieses Forum 'ANSI C'. Somit geht's hier um C in allen Version K&R-C, C89 und C99. Demnach sprechen wir alle von C-Compilen.

    Das Programm kann abstürzen. Das hängt aber nicht am Compiler, sondern an der Umgebung, in der das Programm ausgeführt wird. Wenn Zeiger anders als gespeichert werden als int-Werte, kann das zu verschiedenen Problemen führen.

    1. Der 'vermeindliche' Zeiger zeigt auf einen ungültigen Speicherbereich
    2. Die Rücksprungadresse von malloc() -> main wird nicht korrekt behandelt, malloc() von einem Zeiger ausgeht, ein int aber 'viel' keiner ist. Damit bleiben 'reste' auf dem Stack liegen. [zugegeben - ein 'gebasteltes' Beispiel - aber denkbar]

    siehe zum ganzen Thema auch: ISO/EIC 9899/1999, 6.3.2.3 Pointers

    [ Dieser Beitrag wurde am 03.01.2003 um 16:40 Uhr von mady editiert. ]



  • Original erstellt von Daniel E.:
    ... Im K&R2 wird er konsequent verwendet ...
    ...

    Aber nicht empfohlen (oder sollte mir das irgendwo entgangen sein).

    Aber nochmal - meine Gründe, wann ein cast OK ist:
    - Der Programmierer kennt sich aus - weiß, was ein cast macht
    - Eine evtl. Portierung nach C++

    Gut - der letzte Punkt ist wohl unwahrscheinlich. Ich geb' Dir aber recht, wenn Deine Bemerkung darauf anspielt, dass das K&R den C-Standard nicht ersetzt.

    [ Dieser Beitrag wurde am 03.01.2003 um 16:39 Uhr von mady editiert. ]


Anmelden zum Antworten