Frage zu Typedef



  • @Bashar sagte in Frage zu Typedef:

    ich lerne gerade C++ neu und bin gerade bei typedef und structen angekommen.

    Du lernst C.
    Du lernst kein C++ (zumindest deinen Codebeispielen zufolge).

    @H-P-Wurst sagte in Frage zu Typedef:

    #include <iostream>

    Das lässt vermuten, dass du einen C++ Compiler zum Lernen von C benutzt; das ist komplett sinnfrei und gerade für einen Lernenden schlecht.



  • @Wutz Also ich benutze Visual Studio 2020. Wie kann ich denn bei VS einen C-Compiler benutzen?



  • @Bashar sagte in Frage zu Typedef:

    Willst du C oder C++ lernen?



  • @H-P-Wurst sagte in Frage zu Typedef:

    @Wutz Also ich benutze Visual Studio 2020. Wie kann ich denn bei VS einen C-Compiler benutzen?

    Indem du die Source-Datei mit der Endung .c abspeicherst oder in den Compiler Optionen das entsprechend einstellst.



  • @Swordfish Das Skript mit dem ich arbeite ist aufgeteilt in einen C- und einen C++ Teil. Momentan bin ich noch im C-Teil



  • Also so funktioniert es jetzt:

    #include <stdio.h>
    
    typedef struct emp_struct
    {
    	char name[10];
    	int employee_no;
    	float salary, tax_to_date;
    } Employee;
    
    typedef Employee Database[10];
    
    void swap(Employee* emp1, Employee* emp2)
    {
    	Employee temp;
    	temp = *emp1;
    	*emp1 = *emp2;
    	*emp2 = temp;
    }
    
    void sort(Database people, int n, int str_size)
    {
    	int i, j;
    
    	for (i = 0; i < n - 1; i++)
    		for (j = i + 1; j > 0; j--)
    
    			if (strcmp(people[j].name, people[j - 1].name) < 0)
    				swap(&people[j], &people[j - 1]);
    
    			else if (strcmp(people[j].name, people[j - 1].name) == 0)
    				if (people[j].employee_no < people[j - 1].employee_no)
    					swap(&people[j], &people[j - 1]);
    }
    
    int main()
    {
    	int i, n, str_size;
    	n = 10;
    	str_size = 10;
    
    	Database people = /*initializer: real DB would read from disk*/
    	{ {"Fred", 10, 10000, 3000},
    	{"Jim", 9, 12000, 3100.5},
    	{"Fred", 13, 1000000, 30},
    	{"Mary", 11, 170000, 40000},
    	{"Judith", 45, 130000, 50000},
    	{"Nigel", 10, 5000, 1200},
    	{"Trevor", 10, 20000, 6000},
    	{"Karen", 10, 120000, 34000},
    	{"Marianne", 10, 50000, 12000},
    	{"Mildred", 10, 100000, 30000}
    	};
    
    	sort(people, n, str_size);
    
    	for (i = 0; i < n; i++)
    		printf("Name%d: %s, Mitarbeiternummer: %d \n", i, people[i].name, people[i].employee_no);
    }
    

  • Mod

    @H-P-Wurst sagte in Frage zu Typedef:

    @Swordfish Das Skript mit dem ich arbeite ist aufgeteilt in einen C- und einen C++ Teil. Momentan bin ich noch im C-Teil

    Dein Script ist falsch. Such dir bitte was anderes. Wurde dir schon gesagt, hast du aber nicht ernst genommen. Musst du aber. Falsches Lehrmaterial ist das schlimmst, was du dir antun kannst. Und ganz wichtig: Entscheide dich für eine Sprache. Wenn ein Buch dir C und C++ beibringen möchte, dann bringt es dir keines davon bei.



  • @H-P-Wurst sagte in Frage zu Typedef:

    Also so funktioniert es jetzt:

    void sort(Database people, int n, int str_size)
    

    Ohje, wieder ein Skript was nicht die korrekten Typen für die Größe von Strings verwendet. int ist dafür nicht ausreichend. Früher (in der guten alten Zeit mit 16Bit Computern oder den ersten 32Bit Systemen) mag das noch funktioniert haben. Mittlerweile kann man in Intels bzw. AMD aktuelle Desktop Plattform 128GB RAM verbauen, da ist es sehr einfach mehr als 2GB für einen String zu verwenden. Der korrekte Typ ist size_t bzw. wenn man es Vorzeichen behaftet haben will ssize_t.



  • @john-0 sagte in Frage zu Typedef:

    Ohje, wieder ein Skript was nicht die korrekten Typen für die Größe von Strings verwendet.

    Nicht alles, was str im Namen hat, wird für Strings verwendet. Und hier wird die Variable gar nicht benutzt.



  • @manni66 sagte in Frage zu Typedef:

    Nicht alles, was str im Namen hat, wird für Strings verwendet. Und hier wird die Variable gar nicht benutzt.

    Es ändert nichts daran, dass im gesamten Code Variablen des Typs int verwendet werden, um über dynamische allozierte Felder zu iterieren. Das ist ein Programmfehler.



  • @john-0 sagte in Frage zu Typedef:

    Der korrekte Typ ist size_t bzw. wenn man es Vorzeichen behaftet haben will ssize_t.

    Rede nur von Sachen, von denen du Ahnung hast. ssize_t ist nur POSIX und kein Bestandteil von ISO C.



  • @Wutz sagte in Frage zu Typedef:

    Rede nur von Sachen, von denen du Ahnung hast. ssize_t ist nur POSIX und kein Bestandteil von ISO C.

    Das von jemanden, der das int Problem unkommentiert durchgehen lässt. Das ergibt UB. Ja, ssize_t ist aus POSIX, aber der Compiler würde das Problem anmerken. Deshalb hatte ich das nicht korrigiert.



  • @john-0 sagte in Frage zu Typedef:

    aber der Compiler würde das Problem anmerken

    LOL
    Leute die nach dem Motto programmieren "der Compiler wirds schon merken" - wann hast du das letzte Mal produktionsrelevanten Code geschrieben, der das mehrstufige Codereview überstanden hat?
    Trolle dich.



  • @Wutz sagte in Frage zu Typedef:

    Leute die nach dem Motto programmieren "der Compiler wirds schon merken" - wann hast du das letzte Mal produktionsrelevanten Code geschrieben, der das mehrstufige Codereview überstanden hat?

    Entweder ist ssize_t definiert, oder es ist nicht definiert. Da kann nichts passieren. Aber du reißt hier die Klappe gewaltig auf und lässt UB durchgehen! Wer ist denn hier der Totalversager was produktionsrelevanten Code anbelangt?



  • @john-0
    Nonsens.
    Depp.
    Mit deinen Ansichten wärst du bei mir im Review gleich rausgeflogen und ich hätte dich zum FirstLevel-Support versetzt, da kannst du mit deinem aufgeschnappten Halbwissen nicht soviel Unheil anrichten.
    Hier ist bzgl. int nirgendwo UB.
    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. (dass hierbei höchstens noch die arithmetic promotion mal mit reinspielt, ändert nichts am Grundsatz, d.h. wenn überhaupt wird in diesem Zusammenhang (implizit) int genannt aber niemals size_t).
    Du hast Pointerarithmetik nicht verstanden und propagierst dein aufgeschnapptes Halbwissen als UB - ein Begriff, den du auch irgendwo aufgeschnappt hast und in deinem beschränkten Horizont einfach nachplapperst.
    Ich empfehle dir N1570 und dort die Kapitel 6.*; wenn du das gelesen, verinnerlicht und in 30 Jahren C-Programmierung nachgewiesen hast es verstanden zu haben, kannst du hier mal wieder vorstellig werden.
    Du hast keine Ahnung.
    Trolle dich.



  • @Wutz sagte in Frage zu Typedef:

    @john-0
    Nonsens.
    Depp.
    Ich empfehle dir N1570 (...)
    Du hast keine Ahnung.
    Trolle dich.

    Ach. Ad hominem. Toll.

    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?

    Ich zitiere mal aus N1570. Kapitel 7.24.1 [String function conventions] - aber eigentlich auch egal, wo:

    1 The header <string.h> declares one type and several functions, and defines one
    macro useful for manipulating arrays of character type and other objects treated as arrays
    of character type.307) The type is size_t and the macro is NULL (both described in
    7.19).

    So, und deiner Meinung nach soll man da lieber int nutzen? Warum wird dann überall in den C-Funktionen wie malloc, memcpy etc. nicht der Parametertyp int gewählt, sondern size_t?



  • @wob Der Programmierer darf ruhig sein Expertenwissen 😉 mit ein bringen, ob int reicht oder size_t nötig ist.



  • Kann man das nicht in einen eigenen Thread auslagern? 🍿



  • @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!