Frage zu Typedef



  • @wob sagte in Frage zu Typedef:

    Sagt der, der aus @john-0 s Aussage, dass int nicht ausreichend ist, wenn int 32 bit hat und man mehr als 2GB große Objekte haben möchte, irgendwas über Array-Subscript herleitet?

    Noch ein Naivling.
    Das was du "irgendwas" nennst ist tiefste Pointerarithmetik, also C Grundlagen. Und der Standard hat den Anspruch, eben unabhängig vom Knowhow gewisser Programmierer immer zu gelten, und beschreibt eben genau keine konkreten Annahmen über Bitbreiten und Gigabytes.
    Und deshalb ist der Gebrauch des Standard-Terms "UB" hier sinnfrei und einfach nur falsch, weil der Standard gerade nicht für konkrete Laufzeitbedingungen geschaffen wurde.
    Wer nicht begreift, was der Standard eigentlich bedeutet und für welche Kontexte er gilt, trotzdem aber der Meinung ist, sich aus dessen Sprachgebrauch bedienen zu müssen, desavouiert sich als ahnungsloser Depp, der ungefragt aufgeschnapptes Halbwissen daherplappert.
    Den einzigen Bezug zum Standard bzgl. des gezeigten Codes habe ich aufgezeigt, und wenn du das nicht verstehst, halte einfach die Klappe.



  • @Wutz sagte in Frage zu Typedef:

    Array-subscript zerfällt in Pointerarithmetik, wobei der eine Operand immer ein Zeiger auf einen (vollständigen) Objekttyp und der andere immer von einem beliebigen Integraltyp (oder enum) ist, nirgends wird hier im Standard size_t gefordert, das hast du irgendwo aufgeschnappt und propagierst es hier als UB.

    Wie sehr willst du dich noch selbst bloßstellen? Jemand mit Intelligenz hätte die Sache nochmals nachgelesen. Du legst hier wieder einen drauf. Meinst du mit aggressiven Verhalten könntest du deine Inkompetenz überdecken?

    int ist auf modernen Betriebssystemen ein 32Bit Datentyp unabhängig davon, ob man sich im 32Bit oder 64Bit Modus befindet. size_t expandiert je nach Modus in 32Bit oder 64Bit, passend zur Zeigergröße und den maximalen Feldgrößen. D.h. es garantiert, dass man mit einem size_t Indextyp über ein Feld iterieren kann.

    Du darfst gerne im nachfolgenden Beispiel, die Funktion wutz_strcpy durch eine von dir optimierte Version ersetzen. Die Randbedingungen sind, es wird keine direkte Zeigerarithmetik gemacht (also keine üblen Tricks wie Zeiger mit p++ hochzählen) und als Indextyp für den Feldzugriff nimmst du wie du die ganze Zeit behauptest bitte schön int.

    Ergänzung: Im 64Bit Modus zu übersetzen.

    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <limits.h>
    #include <stdint.h>
    
    
    char* wutz_strcpy (char* dest, const char* src) {
    	int src_length = strlen (src);
    
    	printf("wutz length      %d\n", src_length);
    	src_length++; // just for copying the nul byte
    
    	for (int i = 0; i < src_length; ++i) {
    		dest[i] = src[i];
    	}
    
    	return dest;
    }
    
    int main () {
    	size_t string_length = 0x00000000FFFFFFFF;
    	string_length += 20;
    
    	char* short_dest   = malloc(32);
    	char short_string[] = "This is a short example string.";
    
    	printf("Testing the wutz like function with a short example.\n");
    
    	wutz_strcpy (short_dest, short_string);
    
    	printf("Short example string, before copy with wutz like function: %s\n", short_string);
    	printf("Short example string, after  copy with wutz like function: %s\n", short_dest);
    	free(short_dest);
    
    	// no with large strings
    
    	printf ("\nJust as to remember the sizes of some C data types, and the size of our long example\n");
    	printf ("string length    %zu\n", string_length);
    	printf ("size_t max value %zu\n", SIZE_MAX);
    	printf ("int    max value %d\n", INT_MAX);
    
    	char* my_string = malloc(string_length+1);
    	char* dest      = malloc(string_length+1);
    	// init with non zero to show effect, no trailing nul byte
    	dest[0] = '\0';
    	for (size_t i = 1; i < string_length+1; ++i) {
    		dest[i] = 'X';
    	}
    
    	for (size_t i = 0; i < string_length; ++i) {
    		my_string[i] = 'a';
    	}
    	my_string[string_length] = '\0';
    
    	FILE *fh = fopen("original.txt", "w");
    	fprintf (fh, "%s", my_string);
    	fclose (fh);
    
    	wutz_strcpy (dest, my_string);
    
    	free(my_string);
    
    	fh = fopen ("wutz_error.txt", "w");
    	fprintf(fh, "%s", dest);
    	fclose (fh);
    
    	free(dest);
    
    	return EXIT_SUCCESS;
    }
    
    

    Du hast Pointerarithmetik nicht verstanden

    Das sagt der richtige!



  • @Wutz sagte in Frage zu Typedef:

    Und deshalb ist der Gebrauch des Standard-Terms "UB" hier sinnfrei

    Dein Problem ist, dass du so wenig Ahnung hast, dass du das Problem und UB schon nicht mehr erkennen kannst.



  • @john-0 sagte in Frage zu Typedef:

    int ist auf modernen Betriebssystemen ein 32Bit Datentyp unabhängig davon, ob man sich im 32Bit oder 64Bit Modus befindet. size_t expandiert je nach Modus in 32Bit oder 64Bit, passend zur Zeigergröße und den maximalen Feldgrößen.

    Davon steht im Standard nichts.
    Und du gebrauchst gleichzeitig Standard-Vokabeln, d.h. du hast nichts verstanden; und hier nochmal für solche Begriffsstutzige wie dich:
    der Standard legt fest: "auf allen Betriebssystemen... gilt..."
    Solche Deppen wie du kommen und gehen, in den letzten 10 Jahren habe ich hier sowas mehrfach gehabt, das geht vorbei.



  • @Wutz sagte in Frage zu Typedef:

    Davon steht im Standard nichts.

    Doch, das steht da drin. Du musst ihn nur endlich mal vollständig lesen und verstehen. D.h. die Norm garantiert nur für size_t, dass man in jeder beliebigen Implementation über Felder (Nachtrag:) vollständig iterieren kann. Für int ist das nicht garantiert, es kann funktionieren, wenn die Felder hinreichend klein sind, aber gerade solcher Dreckscode sollte bei einem Codereview eliminiert werden.

    Ein real existierendes Beispiel habe ich hier gepostet, aber deine Arroganz hindert dich daran es zu verstehen.

    Nachtrag: Mein Beispiel zeigt gerade, dass der grobe Unfug, den du die ganze Zeit behauptest eben nicht auf allen Betriebssystemen erfüllt ist. Nutzt man size_t in der Funktion wutz_strcpy funktioniert sie immer auf jeder Plattform unabhängig davon, welches Programmiermodell genutzt wird (16Bit, 32Bit oder 64Bit).



  • @Wutz sagte in Frage zu Typedef:

    Noch ein Naivling.
    Das was du "irgendwas" nennst ist tiefste Pointerarithmetik, also C Grundlagen.

    Ja und? Ich habe nie bestritten, dass man int als Array-Subscript nutzen kann oder gesagt, dass das "irgendwas" nicht korrekt ist. Du schreibst da eine lange Abhandlung, die zwar korrekt ist, aber keinen Zusammenhang zu dem genannten Problem hat, dass int nicht vom Standard garantiert immer ausreichend groß ist. In vielen realen Fällen, die @DirkB hier Expertenwissen nennt, reicht int natürlich. Aber @john-0 hatte ja gerade ein Beispiel gebracht, wo das nicht reicht. Und wenn du eine wiederverwertbare Funktion schreiben willst, warum willst du sie dann unbedingt auf int einschränken?

    Falls du verstanden haben solltest, dass irgendwer von uns meint, dass jedes mal, wenn man eine int-Variable als Array-Index nutzt, UB auftritt, dann hast du das falsch verstanden. Der Punkt ist andersrum. Der Standard garantiert nicht, dass int ausreicht und es gibt Fälle, wo int tatsächlich nicht groß genug ist. Das ist etwas anderes als "Der Standard garantiert, dass int nicht ausreicht". Letztes ist falsch.

    Propagierst du für time_t eigentlich auch int? Auch hier gilt ja die Situation, dass die Größen nicht exakt vorgegeben sind. Und auch hier "reicht" ein 32-bittiger int (so dein System denn int=32 bit hat) für ein aktuelles Datum noch aus. Und der Standard garantiert dir nicht, dass time_t 64 Bit hat.

    Sagen wir es mal so: wer weiß denn schon, wie groß 2038 oder wann auch immer der RAM so ist und wie verbreitet int mit 32 Bit dann noch ist. Nehmen wir mal an, dass da viel mehr Speicher verbaut ist und Programme auch viel mehr Speicher brauchen und dass int immer noch auf irgendeiner modernen Plattformen 32 Bit hat. Dann hättest du den Fall, dass int nicht reicht, viel häufiger als heute.



  • int muss nicht grösser als 16 Bit sein. Soviel nur mal dazu. Aber natürlich wäre es vollkommen doof für Strings > 32K zu planen. Sowas macht ja keiner.



  • @hustbaer sagte in Frage zu Typedef:

    int muss nicht grösser als 16 Bit sein. Soviel nur mal dazu. Aber natürlich wäre es vollkommen doof für Strings > 32K zu planen. Sowas macht ja keiner.

    Famous last words: „Sowas macht ja keiner.“? Genau diese Einstellung für immer wieder zum großen Knall. Alle OS-Funktionen nutzen aus gutem Grund für die Längenargumente bei C-String-Funktionen size_t. Es ist also valide solch großen Strings zu nutzen, und ich habe schon Strings genutzt die deutlich länger als 32k waren. Es handelte sich um E-Mails mit Attachments im Firmenverkehr, da waren die Mails deutlich größer als 32k. Da das ganze Zeug als Base64 kodiert war, musste man es zuerst in Binär umwandeln, um es dann als Blob in der DB speichern zu können.

    Und im HPC hat man ganz schnell double complex Matrizen mit 10.000×10.000 Einträgen, wenn das nicht reicht, muss man 20.000×20.000 oder sogar noch mehr nehmen. Wer meint mit dem Indextyp int könne man in Zeiten von 64Bit OS und Hauptspeicher im Bereich einiger TB noch auskommen, der lebt wirklich noch im 20. Jahrhundert.

    Nachtrag:
    Entschuldigung hustbaer: ohne Smiley kam das nicht gleich zu 100% herüber, und ich bin da momentan etwas gereizt, weil ich der Vergangenheit Dreckscode solcher geistigen Überflieger korrigieren musste.



  • @john-0 Du musst mal deinen Ironiedetektor nachjustieren. 🙂



  • @Bashar sagte in Frage zu Typedef:

    @john-0 Du musst mal deinen Ironiedetektor nachjustieren. 🙂

    Sorry, in den Textforen kommt das immer wieder schlecht herüber, und hier tummeln sich einige „Koryphäen“, so dass man manchmal nicht weiß, ob eine Anmerkung nun ironisch oder todernst gemeint war.