Zeiger auf Literal



  • Hallo NDEBUG,

    ich habe das mal mit deinem Ansatz versucht, habe da aber so meine Probleme mit...

    (1.) ich möchte nur "stdio" und "stdlib" in mein Project einbinden. Ich habe jetzt x Funktionen geschrieben, bei denen das auch hingehauen hat. Das werd ich jetzt nicht wegen einer Funktion ändern.

    Aber aus mir nicht erfindlichen Gründen läuft diese Sch*** funktion immer noch nicht! Alle weitere -> Kommentare im Quelltext...

    int copystring(char *source, char *target,int start, int length, char *ifempty){
    	//returns 1, if no valid character (A..Z, a..z, 0..9, space) was found
    	//returns 0, if at least 1 letter was found
    	int i = 0;
    	int j = 0;
    	int len = length;
    
    	//Ich deklariere oldtarget als "Zeiger auf Char" und initialisiere oldtarget mit der Adresse von target...
    	//char *oldtarget = target;
    	char *oldtarget = &target[0];
    
    	//Aus Performance-Gründen lass ich dass hier mal... - oder?
    	/*
        for(i = start, j = 0; j < length && source[i] != '\0'; i++) { 
            if((source[i] > 64 && source[i] < 91) || (source[i] > 96 && source[i] < 123) || (source[i] > 47 && source[i] < 58) || (source[i] == 32)) 
                target[j++] = source[i]; 
        }
    
    	if(j > 0) { 
            target[j] = '\0'; 
            return 0; 
        }
    	for (i = 0; ifempty[i] != 0; i++) target[i] = ifempty[i]; 
    	target[i] = '\0';
    	return 1;
    	*/
    
    	//Die Adresse der Quellzeichenkette wird um "start" Zeichen vorgerückt (funktioniert auch)...
    	source += start;
    	//Solange "length" noch nicht 0 ist UND in "source[]" auch noch kein 0-Char vorkommt...
    	while (length-- && *source) {
    		//...kopiere "source[]" nach "target[]"...
    		if ((*source > 64 && *source < 91) || (*source > 96 && *source < 123) || (*source > 47 && *source < 58)){;
    			// Zahlen: 48 - 57
    			// Großbuchstaben: 65 - 90
    			// Kleinbuchstaben: 97 - 122
    			*target = *source;
    			target++;
    			// "i" soll nur 1 werden, wenn irgendein Zeichen (s. o.) gefunden wurde...
    			i = 1;
    		}if(*source == 32){
    			*target = *source;
    			target++;
    		}
    		//Source wandert IMMER eins vor, target nur wenn es ein Zeichen zu kopieren gibt...
    		source++;
    	}
    	//Das letzte Zeichen von target auf 0 setzen...
    	*target = 0;
    
    	//Bis HIER scheint alles zu funktionieren. Aber jetzt...
    
    	//Wenn kein Zeichen (außer dem Leerzeichen) gefunden wurde, dann...
    	if (i = 0) {
    		//Die Adresse von target auf den Anfangswert zurücksetzen...
    		target = oldtarget;
    		//So scheint es auch nicht zu klappen (???)...
    		//target = &target[0];
    		//Für den Fall dass *ifempty eine leere Zeichenkette ist, das erste Zeichen von target auf 0 setzen...
    		*target = 0;
    		//Solange *ifempty nicht das 0-Char ist UND die Länge hinhaut...
    		while(*ifempty && len--){
    			//... ifempty nach target kopieren...
    			*target = *ifempty;
    			target++;
    			ifempty++;
    		}
    		//Das letzte Zeichen von target auf 0 setzen...
    		*target = 0;
    		//"return 1" kommt irgendwie nie vor, ist so mein Eindruck... - ich hab ja keinen schönen debugger :-(
    		return 1;
    	}
    	return 0;
    }
    

    Also nur mal so zum Verständnis. Wenn...

    char var[10];
    char *ptr;
    var[0] = 75;
    var[1] = 100;
    ptr = &var[0];
    ptr++;
    

    Hat sich jetzt die Adresse von var[0] geändert? Doch wohl nicht, oder? var[0] ist doch 75 und nicht 100, oder?

    Schönes WE



  • Ich habe jetzt endlich alle Fehler gefunden (siehe Kommentare im Quelltext)!!!

    int copystring(char *source, char *target,int start, int length, char *ifempty){
    	int i = 0;
    	int j = 0;
    	int len = length;
    	char *oldtarget;
    	oldtarget = target;
    	source += start;
    	while (length-- && *source) {
    		if ((*source > 64 && *source < 91) || (*source > 96 && *source < 123) || (*source > 47 && *source < 58)){;
    			*target = *source;
    			target++;
    			i = 1;
    		}if(*source == 32){
    			*target = *source;
    			target++;
    		}
    		source++;
    	}
    	*target = 0;
    	//Wenn man Vergleichs- und Zuweisungsoperatoren verwechselt :-)...
    	//"if (i = 0)" war natürlich falsch.
    	if (i == 0) {
    		//Hier musste "target" aus "oldtarget" gelesen werden, weil 
    		//sich durch "target++" wirklich auch "&target[0]" geändert hat! - Wie krass! 
    		//(siehe Erklärung am Ende des letzten Post)
    		target = oldtarget;
    		*target = 0;
    		while(*ifempty && len--){
    			*target = *ifempty;
    			target++;
    			ifempty++;
    		}
    		*target = 0;
    		return 1;
    	}
    	return 0;
    }
    

    Na dann besonderen Dank an NDEBUG! 🙂



  • hardgecodete ASCII-Zahlen sind unschön und machen den Code unlerserlich. Am besten so:

    if ((*source >= 'A' && *source <= 'Z') || (*source >= 'a' && *source <= 'z') || (*source >= '0' && *source <= '9'))
    ...
    if(*source == ' ')
    

    man sieht sofort auf den ersten Blick, was man meint. Wobei noch viel einfacher (schöner und portabler) wäre es mit

    if(isalnum(*source))
    ...
    if(isspace(*source))
    


  • Du brauchst Performance? Hm. Vielleicht mach ich mir morgen mal den Spaß und laß unsere beiden Funktionen gegeneinader antreten. Array Zugriffe werden intern von C in Pointer Zugriffe umgewandelt. So wird aus array[j] -> *(array + j).
    Ma schaun ich werd mal die Zeiten bei 10.000 Kopieraktionen von zufälligen 128 Byte langen Strings mit zufälligem Anfangs- und Endpunkt messen. Ich hab noch keine Ahnung wer gewinnt. Aber es intressiert mich einfach. Ich poste morgen hier die Ergebnisse...



  • NDEBUG schrieb:

    Array Zugriffe werden intern von C in Pointer Zugriffe umgewandelt. So wird aus array[j] -> *(array + j).

    nö, warum sollte C sowas tun?
    🙂



  • ~fricky schrieb:

    NDEBUG schrieb:

    Array Zugriffe werden intern von C in Pointer Zugriffe umgewandelt. So wird aus array[j] -> *(array + j).

    nö, warum sollte C sowas tun?
    🙂

    warum nicht.

    NDEBUGs beschreibung erklärt mir endlich mal, warum man immer, wo array[j] geht, auch j[array] geht. weil *(array + j) == *(j + array). weil array + j == j + array.
    welche tatsachen sprechen für dein "nö, warum sollte C sowas tun?"?



  • Meine Frage wäre wie sollte C es denn intern ohne Zeigerzugriffe machen?



  • volkard schrieb:

    ~fricky schrieb:

    NDEBUG schrieb:

    Array Zugriffe werden intern von C in Pointer Zugriffe umgewandelt. So wird aus array[j] -> *(array + j).

    nö, warum sollte C sowas tun?
    🙂

    warum nicht.
    NDEBUGs beschreibung erklärt mir endlich mal, warum man immer, wo array[j] geht, auch j[array] geht. weil *(array + j) == *(j + array). weil array + j == j + array.
    welche tatsachen sprechen für dein "nö, warum sollte C sowas tun?"?

    weil eine umwandlung ein unnötiger umweg wäre. ein C-compiler versteht alle diese ausdrücke und macht exakt das gleiche daraus (möglicherweise schon so, dass er intern eine eine funktion aufruft: 'indirekte_addressierung_mit_offset(a,b)'). aber davon sieht man im output nix mehr.

    Meine Frage wäre wie sollte C es denn intern ohne Zeigerzugriffe machen?

    unterschiedlich. bei 'nem konstanten indexwert könnte z.b. der compiler schon die absolute adresse berechnen. aber was am ende rauskommt, ist ja von der ziel-CPU abhängig. wenn die nichts zeiger-änliches kennt, dann müssen C-zeiger, arrays, etc. irgendwie simuliert werden.
    🙂



  • ~fricky da haste aber deine Hausaufgaben nicht gemacht:

    In evaluating a[i], C converts it to *(a+i) immediately; the two forms are equivalent.

    "The C Programming Language - Ansi C - 2nd Edition", Brian W. Kernighan, Dennis M. Ritchie (Seite 89)



  • Ich hab den Test mal laufen lassen. Hier der Testcode:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    #include <assert.h>
    #include <windows.h>
    
    // timer
    static _int64 ticks_per_sec;
    static _int64 timer_start;
    static float secs_per_tick;
    
    void timer_init() {
    	printf("Initializing timer ... ");
        if(!QueryPerformanceFrequency((LARGE_INTEGER *)&ticks_per_sec)) {
            printf("Error: No perfomance counter available.\n");
            exit(1);
        } else {
    		QueryPerformanceCounter((LARGE_INTEGER *)&timer_start);
    		secs_per_tick = ((double)1.0)/((double)ticks_per_sec);
    	}
        printf("OK\n");
    }
    
    float query_timer() {
    	_int64 time;
    
        QueryPerformanceCounter((LARGE_INTEGER *)&time);
        return(((float)(time - timer_start)) * secs_per_tick);
    }
    
    // rand stuff
    void rand_init(void) {
        printf("Initializing random number generator ... ");
        srand((int)query_timer());
        printf("OK\n");
    }
    
    int rand_get(int min, int max) {
        return rand() % (max - min + 1) + min;
    }
    
    // test stuff
    #define MAX_STRINGS     50000
    #define MAX_STRINGLEN   128
    static char teststrings[MAX_STRINGS][MAX_STRINGLEN];
    static char from_else[MAX_STRINGLEN] = "String was not copied.";
    
    // testfunction bgeissl
    int copystring_bgeissl(char *source, char *target,int start, int length, char *ifempty){
        int i = 0;
        int j = 0;
        int len = length;
        char *oldtarget;
        oldtarget = target;
        source += start;
        while (length-- && *source) {
            if ((*source > 64 && *source < 91) || (*source > 96 && *source < 123) || (*source > 47 && *source < 58)){;
                *target = *source;
                target++;
                i = 1;
            }if(*source == 32){
                *target = *source;
                target++;
            }
            source++;
        }
        *target = 0;
        //Wenn man Vergleichs- und Zuweisungsoperatoren verwechselt :-)...
        //"if (i = 0)" war natürlich falsch.
        if (i == 0) {
            //Hier musste "target" aus "oldtarget" gelesen werden, weil
            //sich durch "target++" wirklich auch "&target[0]" geändert hat! - Wie krass!
            //(siehe Erklärung am Ende des letzten Post)
            target = oldtarget;
            *target = 0;
            while(*ifempty && len--){
                *target = *ifempty;
                target++;
                ifempty++;
            }
            *target = 0;
            return 1;
        }
        return 0;
    }
    
    // testfunction NDEBUG
    // removed dependency on ctype.h and string.h 
    int copystring_NDEBUG(const char from[], char to[], int start, int length, const char from_else[]) {
        int i, j;
    
        for(i = start, j = 0; j < length && from[i] != '\0'; i++) {
            if((from[i] >= '0' && from[i] <= '9') || (from[i] >= 'A' && from[i] <= 'Z') ||
               (from[i] >= 'a' && from[i] <= 'z') || from[i] == ' ')
                to[j++] = from[i];
        }
    
        if(j > 0) {
            to[j] = '\0';
            return 0;
        }
    
        while(*to++ = *from_else++);
        return 1;
    }
    
    enum {
        bgeissl, NDEBUG
    };
    
    int main(int argc, char *argv[]) {
        char to[2][MAX_STRINGLEN];
        int ret[2];
        int i, j, str_begin, str_end, str_len;
        float time_start, time_end, time[2] = {0.0, 0.0};
    
        // setup stuff
        timer_init();
        rand_init();
    
        // init teststrings array with random strings
        // only contain printable chars from 28 - 254
        printf("Initializing test array ... ");
        for(i = 0; i < MAX_STRINGS; i++) {
            for(j = 0; j < MAX_STRINGLEN; j++) {
                teststrings[i][j] = (char)rand_get(28, 254);
            }
            teststrings[i][MAX_STRINGLEN - 1] = '\0';
        }
        printf("OK");
    
        for(i = 0; i < MAX_STRINGS; i++) {
            // make the start and end random
            str_begin = rand_get(0, (MAX_STRINGLEN / 2) - 1);
            str_end = rand_get((MAX_STRINGLEN / 2) + 1, MAX_STRINGLEN);
            str_len = str_end - str_begin;
    
            // run bgeissl
            time_start = query_timer();
            ret[bgeissl] = copystring_bgeissl(teststrings[i], to[bgeissl], 0, MAX_STRINGLEN, from_else);
            time_end = query_timer();
            time[bgeissl] += time_end - time_start;
    
            // run NDEBUG
            time_start = query_timer();
            ret[NDEBUG] = copystring_NDEBUG(teststrings[i], to[NDEBUG], 0, MAX_STRINGLEN, from_else);
            time_end = query_timer();
            time[NDEBUG] += time_end - time_start;
    
            // assert total equality
            assert(!strcmp(to[bgeissl], to[NDEBUG]));
            assert(ret[bgeissl] == ret[NDEBUG]);
    
            // every now and then print some reference texts
            if(i % (MAX_STRINGS/10) == 0) {
                printf("\nRun(#%5d):\n", i);
                printf("=============\n");
                printf("string: %s\n", teststrings[i]);
                printf("bgeissl: %s ret: %d\n", to[bgeissl], ret[bgeissl]);
                printf("NDEBUG : %s ret: %d\n", to[NDEBUG], ret[NDEBUG]);
            }
        }
    
        printf("\n\nRESULTS after %d runs:\n", MAX_STRINGS);
        printf("bgeissl: overall: %f secs\n", time[bgeissl]);
        printf("NDEBUG : overall: %f secs\n\n\n", time[NDEBUG]);
    
        system("pause");
        return 0;
    }
    

    Und hier ein Testlauf:

    Initializing timer ... OK
    Initializing random number generator ... OK
    Initializing test array ... OK
    Run(#    0):
    =============
    string: B›ÃøÝO$ÞÎÏ#R‡;xÐJ´x‹v8bØPáÛH̤»ä‰š âÖ3`gÑH¶Ñ(sE¦•1Œdc§Yà{ZªÞs!L¾²93K« OP3£Fc‚å+—(€lˆd”ƒSžü…ŽÆ8‚’…é²8Óhó>Ãf;¼ù“¡È~õ^IÈ\‡¹ôâ
    bgeissl: BORxJxv8bPH3gHsE1dcYZsL93KOP3FcldS88hfI ret: 0
    NDEBUG : BORxJxv8bPH3gHsE1dcYZsL93KOP3FcldS88hfI ret: 0
    
    Run(# 5000):
    =============
    string: ÒéfŸ”‹V[IéÕµl”,×!ÎûT2`&º†NÞµ:Ã#X\¶Š”è&3a~‘<6÷ño¶óÎ’8Ÿ©tûU‘ ¡›hý¹EýÅoŸÔmµüTT„P*à…QUîp²7¿Dþ×Çu•ýÈ[ã6ÑQ6¿9ʈÀÃq^‰ä^1ß¼‘ÒØË‰+K
    bgeissl: fVIlT2NX3a6o8tUhEomTTPQUp7Du6Q69q1K ret: 0
    NDEBUG : fVIlT2NX3a6o8tUhEomTTPQUp7Du6Q69q1K ret: 0
    
    Run(#10000):
    =============
    string: L;sUJK{x{Ùæz5ßF÷î?ì»Aµt™˜ÇrÁ¿ ~oèá|!‡ôékrê·åÜä³”°y.}Š7!äŽÍÀöºHOXîѪ[ ¨ˆú^°—de?Ð^ÏU9£YÇ4.Eèžö¥Ô©9»T¹%—¨œ}æúJ菦ƒW_>dû™äŠ”˜
    bgeissl: LsUJKxz5FAtr okry7HOX deU9Y4E9TJWd ret: 0
    NDEBUG : LsUJKxz5FAtr okry7HOX deU9Y4E9TJWd ret: 0
    
    Run(#15000):
    =============
    string: tyrÈrÌýdü`²õRAš×¦#¤`žê›1œúªÎ%ÅõçîRrɹ7CÓ” qšbJçΏÙw­›‘Àâ9psG®»Y…NEë›:ÈûÚ dÛtZé.(††,,7£J”ë\ q:?ãûp¢O¿‹ B,/ˆ£ôŽ¥ØéPYiõl„ѼkØ
    bgeissl: tyrrdRA1Rr7CqbJw9psGYNE dtZ7JqpOBPYilk ret: 0
    NDEBUG : tyrrdRA1Rr7CqbJw9psGYNE dtZ7JqpOBPYilk ret: 0
    
    Run(#20000):
    =============
    string: h c‚kæ÷³¨_ÚÓäb¥½€ìRwŠÅš<ž¯‰ˆò>šÉ³nùúqw„ääÆÂœ¸ƒ­ÀrúÞ[œÝî1àtlâæD×|Cå|JÍJíËç>6ZјP/­¨Eº-oÐßjiü—è*SÊ?¬1¢‰\Î(‹ï¥Æ{Š«mÍëÎàGä<B5
    bgeissl: h ckbRwnqwr1tlDCJJ6ZPEojiS1mGB5 ret: 0
    NDEBUG : h ckbRwnqwr1tlDCJJ6ZPEojiS1mGB5 ret: 0
    
    Run(#25000):
    =============
    string: )³FùDݺ€ôE¼5£‰ø4QªeOë絯ª^äû—]à,߆[Ô[¥cà5×Dl³–4‰Ãy“Ý(þ8ûÁæ)ñ;S;í¤áDg9äK.È÷±´“fEn{’£½S~'Pá@c¦Ë§‡žÓÞµœg\ûA­±\®üØ’2LÇÌ=ü·
    bgeissl: FDE54QeOc5Dl4y8SDg9KfEnSPcgA2L ret: 0
    NDEBUG : FDE54QeOc5Dl4y8SDg9KfEnSPcgA2L ret: 0
    
    Run(#30000):
    =============
    string: ˜¯kúÑÙ`j£ú¨%¹Œ½w`Œ]z dZ-WKD€PA´¢ØõÞR…`¹#èUÞ@ªè’°¼„}2Þ7.אM<»^ÍC¸4\`è6Èz*µ“pÈ€iùQÓ·E‘ö£0ŒIŽe¿)q\¶Ã–u°c‡FE&œ'YC§N¡{{âSxŒˆo@ê
    bgeissl: kjwzdZWKDPARU27MC46zpiQE0IequcFEYCNSxo ret: 0
    NDEBUG : kjwzdZWKDPARU27MC46zpiQE0IequcFEYCNSxo ret: 0
    
    Run(#35000):
    =============
    string: @d‚“îpÂñ0˜òûí¤FÊšf’8úpj.†tq›¯Ì©Yž7m˜ ÛQ‡Û•‰³"ùŸv{=™¯M2×F‘óÆÕã÷ý§rô,È7BPJTÞþFîi!œ‚XÑêCÒMøæ^GÆõïÉÚErŸØ4’3=‰[k­£@n—¦ã/{j‚fÍ
    bgeissl: dp0Ff8pjtqY7mQvM2Fr7BPJTFiXCMGEr43knjf ret: 0
    NDEBUG : dp0Ff8pjtqY7mQvM2Fr7BPJTFiXCMGEr43knjf ret: 0
    
    Run(#40000):
    =============
    string: HµŠ˜™î¶æröJRéÅ«k¼ښ`&–±V‹†ªË,?IĴý”¯kÇówºœCxŸêžÑ9”^]OM”­=ñǺHYyoªØjwë…vºHU}˜‡¤¤î똓dÃ?‡MDÜEÃL¥ËûF2¤'*Š>j¤ž«ÛB06 3J»¦B 3Ýò
    bgeissl: HrJRkVkwCx9OMHYyojwvHUdMDELF2jB06 3JB 3 ret: 0
    NDEBUG : HrJRkVkwCx9OMHYyojwvHUdMDELF2jB06 3JB 3 ret: 0
    
    Run(#45000):
    =============
    string: þ¿…wú¶sAuÆqªýUÕ£;áºÍjýL@øŽ…þÕ= è·ãÉ¢g¼äqñ>꘡MbôRù{ÕuÁ¹^ê—Ùs²@3ù/¢¦`6ƒüâIé{“óáÈí¦LýR&³,¾8¹#1ôéA¨^3Ý—#WnFbAx,ϱûV{?kwT¨2eqÈ
    bgeissl: wsAuqUjL gqMbRus36ILR81A3WnFbAxVkwT2eq ret: 0
    NDEBUG : wsAuqUjL gqMbRus36ILR81A3WnFbAxVkwT2eq ret: 0
    
    RESULTS after 50000 runs:
    bgeissl: overall: 0.130833 secs
    NDEBUG : overall: 0.139831 secs
    

    EDIT: wenn ich den Start des String randomize und die Länge die kopiert werden soll auch. Liefern unsere Funktionen nicht den gleichen String zurück! Assert schlägt hier fehl!



  • Außerdem habe ich keinerlei Optimierierung unter Visual Studio eingeschaltet. Es war die Standard Debug Einstellung von Visual Studio 2008 Professional.



  • Hier ein Testlauf mit den Standard Release Einstellungen von Visual Studio:

    Initializing timer ... OK
    Initializing random number generator ... OK
    Initializing test array ... OK
    Run(#    0):
    =============
    string: B›ÃøÝO$ÞÎÏ#R‡;xÐJ´x‹v8bØPáÛH̤»ä‰š âÖ3`gÑH¶Ñ(sE¦•1Œdc§Yà{ZªÞs!L¾²93K« OP3£Fc‚å+—(€lˆd”ƒSžü…ŽÆ8‚’…é²8Óhó>Ãf;¼ù“¡È~õ^IÈ\‡¹ôâ
    bgeissl: BORxJxv8bPH3gHsE1dcYZsL93KOP3FcldS88hfI ret: 0
    NDEBUG : BORxJxv8bPH3gHsE1dcYZsL93KOP3FcldS88hfI ret: 0
    
    Run(# 5000):
    =============
    string: ÒéfŸ”‹V[IéÕµl”,×!ÎûT2`&º†NÞµ:Ã#X\¶Š”è&3a~‘<6÷ño¶óÎ’8Ÿ©tûU‘ ¡›hý¹EýÅoŸÔmµüTT„P*à…QUîp²7¿Dþ×Çu•ýÈ[ã6ÑQ6¿9ʈÀÃq^‰ä^1ß¼‘ÒØË‰+K
    bgeissl: fVIlT2NX3a6o8tUhEomTTPQUp7Du6Q69q1K ret: 0
    NDEBUG : fVIlT2NX3a6o8tUhEomTTPQUp7Du6Q69q1K ret: 0
    
    Run(#10000):
    =============
    string: L;sUJK{x{Ùæz5ßF÷î?ì»Aµt™˜ÇrÁ¿ ~oèá|!‡ôékrê·åÜä³”°y.}Š7!äŽÍÀöºHOXîѪ[ ¨ˆú^°—de?Ð^ÏU9£YÇ4.Eèžö¥Ô©9»T¹%—¨œ}æúJ菦ƒW_>dû™äŠ”˜
    bgeissl: LsUJKxz5FAtr okry7HOX deU9Y4E9TJWd ret: 0
    NDEBUG : LsUJKxz5FAtr okry7HOX deU9Y4E9TJWd ret: 0
    
    Run(#15000):
    =============
    string: tyrÈrÌýdü`²õRAš×¦#¤`žê›1œúªÎ%ÅõçîRrɹ7CÓ” qšbJçΏÙw­›‘Àâ9psG®»Y…NEë›:ÈûÚ dÛtZé.(††,,7£J”ë\ q:?ãûp¢O¿‹ B,/ˆ£ôŽ¥ØéPYiõl„ѼkØ
    bgeissl: tyrrdRA1Rr7CqbJw9psGYNE dtZ7JqpOBPYilk ret: 0
    NDEBUG : tyrrdRA1Rr7CqbJw9psGYNE dtZ7JqpOBPYilk ret: 0
    
    Run(#20000):
    =============
    string: h c‚kæ÷³¨_ÚÓäb¥½€ìRwŠÅš<ž¯‰ˆò>šÉ³nùúqw„ääÆÂœ¸ƒ­ÀrúÞ[œÝî1àtlâæD×|Cå|JÍJíËç>6ZјP/­¨Eº-oÐßjiü—è*SÊ?¬1¢‰\Î(‹ï¥Æ{Š«mÍëÎàGä<B5
    bgeissl: h ckbRwnqwr1tlDCJJ6ZPEojiS1mGB5 ret: 0
    NDEBUG : h ckbRwnqwr1tlDCJJ6ZPEojiS1mGB5 ret: 0
    
    Run(#25000):
    =============
    string: )³FùDݺ€ôE¼5£‰ø4QªeOë絯ª^äû—]à,߆[Ô[¥cà5×Dl³–4‰Ãy“Ý(þ8ûÁæ)ñ;S;í¤áDg9äK.È÷±´“fEn{’£½S~'Pá@c¦Ë§‡žÓÞµœg\ûA­±\®üØ’2LÇÌ=ü·
    bgeissl: FDE54QeOc5Dl4y8SDg9KfEnSPcgA2L ret: 0
    NDEBUG : FDE54QeOc5Dl4y8SDg9KfEnSPcgA2L ret: 0
    
    Run(#30000):
    =============
    string: ˜¯kúÑÙ`j£ú¨%¹Œ½w`Œ]z dZ-WKD€PA´¢ØõÞR…`¹#èUÞ@ªè’°¼„}2Þ7.אM<»^ÍC¸4\`è6Èz*µ“pÈ€iùQÓ·E‘ö£0ŒIŽe¿)q\¶Ã–u°c‡FE&œ'YC§N¡{{âSxŒˆo@ê
    bgeissl: kjwzdZWKDPARU27MC46zpiQE0IequcFEYCNSxo ret: 0
    NDEBUG : kjwzdZWKDPARU27MC46zpiQE0IequcFEYCNSxo ret: 0
    
    Run(#35000):
    =============
    string: @d‚“îpÂñ0˜òûí¤FÊšf’8úpj.†tq›¯Ì©Yž7m˜ ÛQ‡Û•‰³"ùŸv{=™¯M2×F‘óÆÕã÷ý§rô,È7BPJTÞþFîi!œ‚XÑêCÒMøæ^GÆõïÉÚErŸØ4’3=‰[k­£@n—¦ã/{j‚fÍ
    bgeissl: dp0Ff8pjtqY7mQvM2Fr7BPJTFiXCMGEr43knjf ret: 0
    NDEBUG : dp0Ff8pjtqY7mQvM2Fr7BPJTFiXCMGEr43knjf ret: 0
    
    Run(#40000):
    =============
    string: HµŠ˜™î¶æröJRéÅ«k¼ښ`&–±V‹†ªË,?IĴý”¯kÇówºœCxŸêžÑ9”^]OM”­=ñǺHYyoªØjwë…vºHU}˜‡¤¤î똓dÃ?‡MDÜEÃL¥ËûF2¤'*Š>j¤ž«ÛB06 3J»¦B 3Ýò
    bgeissl: HrJRkVkwCx9OMHYyojwvHUdMDELF2jB06 3JB 3 ret: 0
    NDEBUG : HrJRkVkwCx9OMHYyojwvHUdMDELF2jB06 3JB 3 ret: 0
    
    Run(#45000):
    =============
    string: þ¿…wú¶sAuÆqªýUÕ£;áºÍjýL@øŽ…þÕ= è·ãÉ¢g¼äqñ>꘡MbôRù{ÕuÁ¹^ê—Ùs²@3ù/¢¦`6ƒüâIé{“óáÈí¦LýR&³,¾8¹#1ôéA¨^3Ý—#WnFbAx,ϱûV{?kwT¨2eqÈ
    bgeissl: wsAuqUjL gqMbRus36ILR81A3WnFbAxVkwT2eq ret: 0
    NDEBUG : wsAuqUjL gqMbRus36ILR81A3WnFbAxVkwT2eq ret: 0
    
    RESULTS after 50000 runs:
    bgeissl: overall: 0.100346 secs
    NDEBUG : overall: 0.096879 secs
    

    Ich mußte das hier ändern:

    //enum { bgeissl, NDEBUG };
    #define bgeissl 0
    #define NDEBUG  1
    


  • NDEBUG schrieb:

    In evaluating a[i], C converts it to *(a+i) immediately.

    einen compiler, der solche sinnlosen zwischenschritte macht, will ich gar nicht verwenden.
    🙂



  • Wieso gibt es da keine Typenprüfung, die sowas verbietet? Wenn man int i und char a[9] anlegt, daß dann tatsächlich i[a] geschrieben werden darf (hab's gerade probiert), finde ich grausam. Ich habe keine Probleme mit der internen Darstellung, aber i ist nunmal kein Pointer, weshalb krieg' ich da nichtmal eine Warning?



  • Wo ist eigentlich nun das Problem? 😕



  • Tim schrieb:

    Wo ist eigentlich nun das Problem? 😕

    Daß das total unlogisch rüberkommt.

    void problem(void)
    {
    	int *check;
    	int i = 3;	// einzelner Integer
    	char a[9];	// a ist (*char)
    
    	*check = 5;
    	a[i] = 'a'; 	// logisch, a ist Basepointer, i wird offset (*char)
    					// wir wollen ja ein array of char auflösen.
    	i[a] = 'b'; 	// unlogisch, ist i ein basepointer auf char oder gar integer?!?
    					// unlogisch ist i ein array?
    					// nein, i ist nur ein Integer!!!
    	a[*check] = 'a'; // logisch, a ist Basepointer, *check zu offset (*char)
    	*check[a] = 'b'; // Operands of + have incompatible types 'int *' and 'char *'.
    					// Type error: pointer expected - Achnee?.
    }
    

    Wo steckt die tiefere Logik dahinter, sowas wie in Zeile 10 zu erlauben? Wann wird aus welchen Vorgaben der Typ gecastet, um diese Zugriffe aufzulösen?



  • pointercrash() schrieb:

    Tim schrieb:

    Wo ist eigentlich nun das Problem? 😕

    Daß das total unlogisch rüberkommt.

    void problem(void)
    {
    	int *check;
    	int i = 3;	// einzelner Integer
    	char a[9];	// a ist (*char)
    
    	*check = 5;
    	a[i] = 'a'; 	// logisch, a ist Basepointer, i wird offset (*char)
    					// wir wollen ja ein array of char auflösen.
    	i[a] = 'b'; 	// unlogisch, ist i ein basepointer auf char oder gar integer?!?
    					// unlogisch ist i ein array?
    					// nein, i ist nur ein Integer!!!
    	a[*check] = 'a'; // logisch, a ist Basepointer, *check zu offset (*char)
    	*check[a] = 'b'; // Operands of + have incompatible types 'int *' and 'char *'.
    					// Type error: pointer expected - Achnee?.
    }
    

    google: C operator precedence...



  • NDEBUG schrieb:

    Ich mußte das hier ändern:

    //enum { bgeissl, NDEBUG };
    #define bgeissl 0
    #define NDEBUG  1
    

    Dir ist aber schon klar, dass NDEBUG ein Makro ist, welches von der Standardbibliothek verwendet wird um zwischen Debug- und Release-Version zu unterscheiden, dieses Makro von Visual Studio sogar automatisch gesetzt wird (im Releasemodus bei Standardprojekteinstellungen) und Du Dir damit höchstwahrscheinlich das Testergebnis verfälscht? 🙂



  • Guter Hinweis. Ich hab die defines geändert nach

    #define bgeissl     0
    #define peterlustig 1
    

    und die notwendigen Veränderungen vorgenommen. Es hat sich an den Ergebnissen aber nix geändert.



  • Tim schrieb:

    google: C operator precedence...

    Achja, jetzt frißt er's.

    Das war aber nicht meine Frage. Ich habe mehrfach über Arrays gelesen, daß der Name als Basispointer gilt und dann der Index dem Typen des Arrays entsprechend als Offset draufgeklatscht wird.

    Nun ist aber i immer noch kein Array, sondern ein Integer. Woher bezieht der Compiler seine Typeninformation bzw. löst die [] wirklich auf?


Anmelden zum Antworten