void* vs. char*



  • icarus2 schrieb:

    casting show schrieb:

    Der echte Tim schrieb:

    int * func_doof (void) {
    	int *r = NULL;
    	r = (int *) malloc (100);
    	return r;
    }
    

    das ist besonders doof [...]

    Das war genau sein Punkt! 🙄

    der bleibt übrig, denn meinen punkt hast du rausgelöscht. 😉



  • casting show schrieb:

    das ist besonders doof, wenn er include<stdlib.h> vergessen hat und sizeof(int)!=sizeof(void*) ist jedenfalls vor C11. casts verdecken potentielle fehler.

    Das ist imho ein recht konstruiertes Beispiel, bzw. wenn solche Fehler passieren (also das Vergessen elementarer Header), dann ist Hopfen und Malz verloren.

    Meine Argumentation gegenüber den Leuten wäre einfach: Der Standard sieht es so vor, warum also meinen cleverer zu sein bzw. eine Konvention mit Füssen zu treten? Aber gut, ich kann mir die "Argumentation" der Kollegen vorstellen, ... ignore? 😃



  • Der echte Tim schrieb:

    casting show schrieb:

    das ist besonders doof, wenn er include<stdlib.h> vergessen hat und sizeof(int)!=sizeof(void*) ist jedenfalls vor C11. casts verdecken potentielle fehler.

    Das ist imho ein recht konstruiertes Beispiel, bzw. wenn solche Fehler passieren (also das Vergessen elementarer Header), dann ist Hopfen und Malz verloren.

    Hast du Recht. Fast jeder verwendet heute eine IDE, die on-the-fly prüft was einer reinhackt. Vergessene headers werden umgehend angemeckert oder gleich automatisch #included.

    Wer aber als Nostalgiker immer noch VI, Emacs, Notepad, NEdit u.ä. und einen alten Compiler benutzt, der wird oft nicht einmal ein Warning bekommen, wenn er eine Library-Funktion ohne Prototyp aufruft.

    Allgemein sollte man bei Casting sehr vorsichtig sein. Ist jedenfalls meine Meinung.



  • Danke für eure Standpunkte!



  • casting show schrieb:

    sizeof(int)!=sizeof(void*)

    diese bedingung ist nur ganz zufällig auf bestimmten systemen erfüllt.
    allgemein steht da aber äpfel != birnen, weil das eine die adressbreite ist und das andere die anzahl der bytes, die eine variable im speicher belegt.

    RollerCaster schrieb:

    Allgemein sollte man bei Casting sehr vorsichtig sein. Ist jedenfalls meine Meinung.

    ein möglicher grund für void-zeiger wäre z.b. sowas:

    void Zeichenfunktion(void *zeichenobjekt, int objekttyp)
    {
    switch(objekttyp)
    {
    case KREIS:
    ZeichneKreis(zeichenobjekt);
    break;
    case RECHTECK:
    ZeichneRechteck(zeichenobjekt);
    break;
    }
    }
    

    der grund dafür wäre, dass sich das "hauptprogramm" nicht weiter darum zu kümmern braucht, welche funktion aufgerufen werden muss, um die gewünschte figur zu zeichnen, was der übersichtlichkeit wieder zugute kommt.



  • Was soll dieses Geflenne, ob void* oder char*?
    Wenn ein Typ undefiniert ist, dann nimmt man void*, da braucht man nicht zu diskutieren.
    Gut, es mag sein, daß das für einen C-Programmierer schon etwas zu abstrakt ist, aber diese Abstraktion sollte man schon einer Hochsprache zuerkennen. 😉



  • Das ist natürlich Quatsch.
    Erstmal ist void* kein undefinierter Typ sondern ein definierter Typ.
    Und weiterhin ist Sinn und Zweck eines (Daten)Zeigers die Dereferenzierung,
    und da wird bei void* nun mal der originale Ausgangstyp (oder kompatibel) benötigt um type punning und damit UB zu vermeiden.
    Ausschließlich für Zwecke, bei denen der Speicher als rohe Bytefolge verarbeitet werden kann/soll, ist void* ohne Originaltypinfo ohne UB verwendbar, da hierbei mit char/signed char/unsigned char ohne strict aliasing break(d.h. ohne UB) gefahrlos gearbeitet werden kann, da void* genau das gleiche (und beste) Alignment gemäß Standard besitzt wie char/signed char/unsigned char.
    Beispiele sind memcpy,fread,fwrite



  • Wutz schrieb:

    ... da void* genau das gleiche (und beste) Alignment gemäß Standard besitzt wie char/signed char/unsigned char.
    Beispiele sind memcpy,fread,fwrite

    Einn schnelles memcpy schaufelt niemals byteweise, sondern mit den größten Schaufeln, die die CPU zur Verfügung stellt. Einzelne Bytes nur für den Rest, oder wenn weniger gefragt ist. 🙂



  • Du hast keine Ahnung, wovon du redest. Also halt die Klappe.
    Wenn du nicht weißt, was Alignment bedeutet, dann halt die Klappe und zeige nicht öffentlich deine Inkompetenz.
    Wenn du nicht weißt, dass der Standard keinerlei Implementierungsvorschriften für Standardfunktionen vorschreibt, dann halt die Klappe und zeige nicht öffentlich deine Inkompetenz.
    Wenn du nicht weißt, dass das Alignmentproblem naturgemäß immer vor jeglicher konkreter Kopieraktion durch die CPU zuschlägt, dann halt die Klappe und zeige nicht öffentlich deine Inkompetenz.



  • Wutz schrieb:

    ... dass das Alignmentproblem naturgemäß immer vor jeglicher konkreter Kopieraktion durch die CPU zuschlägt
    ...

    Aus diesem Grund muss der Speicher in drei Schritten kopiert werden:

    1. Byteweises Kopieren bis zur Alignment-Grenze,
    2. Turbo einschalten: (DMA, Schleife unter Nutzung voller Registerbreiten, usw.),
    3. Byteweises Kopieren des Rests.

    Die Argumente der memcpy-Funktion bieten alles, was für dafür nötig ist.

    Aber es ist wohl müssig, das einem Informatikstudium-Abbrecher wie dir zu erzählen, der außer Uni-Übungen und privaten Gehversuchen in C diesbezüglich noch nichts geleistet hat.



  • Kritiker1 schrieb:

    Wutz schrieb:

    ... dass das Alignmentproblem naturgemäß immer vor jeglicher konkreter Kopieraktion durch die CPU zuschlägt
    ...

    Aus diesem Grund muss der Speicher in drei Schritten kopiert werden:

    ...

    Aber es ist wohl müssig, das einem Informatikstudium-Abbrecher wie dir zu erzählen, der außer Uni-Übungen und privaten Gehversuchen in C diesbezüglich noch nichts geleistet hat.

    Klingt so, als ob Wutz was anderes behauptet hätte, hat er aber doch nicht?!



  • Dorfdepp.
    Du hast immer noch nichts verstanden.
    Wer lesen kann, ist klar im Vorteil.
    Wenn du mal 25 Jahre Erfahrungen in praktischer C Programmierung haben solltest, kannst du hier mal wieder vorbeischauen - und wirst dann über dein naives Nachgeplapper von aufgeschnapptem Halbwissen nur den Kopf schütteln können.



  • Belli schrieb:

    Klingt so, als ob Wutz was anderes behauptet hätte, hat er aber doch nicht?!

    Er hat viel anderes behauptet. Lies doch einfach mal seinen Beitrag. Ich könnte schwören, dass er jemand ist, der sich tierisch was darauf einbildet, weil er etwas C kann, aber praktisch nie etwas auf die Reihe gebracht hat.



  • Wutz schrieb:

    .
    Wenn du mal 25 Jahre Erfahrungen in praktischer C Programmierung haben solltest ...

    Dann zeig mal bitte deine Referenzen. Ansonsten halte ich dich für einen Faker und Blender. Mehr nicht.

    Ich hoffe, dass ich mich täusche!



  • Naiver und durchschaubarer Versuch eines Ahnungslosen. Damit bist du hier nicht der Erste.


  • Mod

    Kritiker1 schrieb:

    Wutz schrieb:

    .
    Wenn du mal 25 Jahre Erfahrungen in praktischer C Programmierung haben solltest ...

    Dann zeig mal bitte deine Referenzen. Ansonsten halte ich dich für einen Faker und Blender. Mehr nicht.

    Ich hoffe, dass ich mich täusche!

    Also ich sehe jede Menge korrekte Aussagen von Wutz über Alignment und Zeigerhandling. Dagegen steht eine ungenaue und irrelevante Aussage über das interne Arbeiten von memcpy und eine Möchtegern-Erwiderung auf Wutz, bei der offenbar nicht einmal gelesen wurde, was Wutz geschrieben hat.

    Also für mich ist ganz klar, wer hier Kompetenz gezeigt hat und wer nur heiße Luft produziert hat (Unnötige Beleidigungen sind aus allen Richtungen gekommen). Wir reden hier von einer Sprache mit genau definierten Regeln, da braucht man keine Zeugnisse¹, um ein Argument zu untermauern. Jeder kann objektiv prüfen, ob eine Aussage richtig oder falsch ist.

    ¹: Und Hinweise auf Erfahrung, wie Wutz sie gerne macht, sind aus dem gleichen Grund irrelevant.



  • Wutz schrieb:

    Das ist natürlich Quatsch.
    Erstmal ist void* kein undefinierter Typ sondern ein definierter Typ.
    Und weiterhin ist Sinn und Zweck eines (Daten)Zeigers die Dereferenzierung,
    und da wird bei void* nun mal der originale Ausgangstyp (oder kompatibel) benötigt um type punning und damit UB zu vermeiden.
    Ausschließlich für Zwecke, bei denen der Speicher als rohe Bytefolge verarbeitet werden kann/soll, ist void* ohne Originaltypinfo ohne UB verwendbar, da hierbei mit char/signed char/unsigned char ohne strict aliasing break(d.h. ohne UB) gefahrlos gearbeitet werden kann, da void* genau das gleiche (und beste) Alignment gemäß Standard besitzt wie char/signed char/unsigned char.
    Beispiele sind memcpy,fread,fwrite

    Natürlich ist "void*" definiert, aber in der Abstraktion der Sprache 'C' ist es ein undefinierter Typ, der erst durch einen Cast seinen Typ bekommt.
    Du spricht hier von der Implementierung, natürlich sollte das ein C-Programmierer auch beachten, aber um einen Code lesbar und pflegbar zu machen, sollte man "void*" als undefiniert betrachten.
    Wenn ich keine Abstraktion will, dann sollte man Assembler verwenden...



  • ralros schrieb:

    Wenn ich keine Abstraktion will, dann sollte man Assembler verwenden...

    C ist sowas wie eine portable Assemblersprache. Recht Maschinennah und von geringem Abstraktionsgrad.



  • Futz schrieb:

    ralros schrieb:

    Wenn ich keine Abstraktion will, dann sollte man Assembler verwenden...

    C ist sowas wie eine portable Assemblersprache. Recht Maschinennah und von geringem Abstraktionsgrad.

    Das will ich ja auch nicht bestreiten, daß ist der Grund, warum ich C liebe, aber wenn man hier schon Diskussionen über "void* vs. char*" führt, dann führt man auch die Sprache C "ad absurdum"...wer solche "Probleme" hat, der soll doch bitte Assembler nutzen! 😃



  • ralros schrieb:

    Natürlich ist "void*" definiert, aber in der Abstraktion der Sprache 'C' ist es ein undefinierter Typ, der erst durch einen Cast seinen Typ bekommt.

    void* ist ein unbestimmter datentyp. undefiniert bedeutet sozusagen "existiert nicht". 🙄

    Futz schrieb:

    C ist sowas wie eine portable Assemblersprache. Recht Maschinennah und von geringem Abstraktionsgrad.

    nein c ist eine hochsprache. ich muss mich da nicht mit registern herumärgern und cpu-funktionen wie z.b. rdtsc kann ich auch nicht direkt aufrufen.


Anmelden zum Antworten