![]() |
![]() |
|
![]() |
![]() |
|
Programmierung Rat & Tat für Programmierer |
![]() |
|
Themen-Optionen | Ansicht |
![]() |
#1 |
Veteran
![]() |
![]() void *nget(struct names *names, const char *name)
{ while (names) { if (strcmp(name,names->name) == 0) return names->value; else names = names->next; } return 0; } Wie ist das möglich??? Habe diesen Code ausschnitt von airstrike, Datei: names.c lg Etienne |
![]() |
![]() |
![]() |
#2 |
Inventar
![]() |
![]() Wäre halt noch ganz brauchbar den Rest des - relevanten - Codes zu sehen und den verwendeten Compiler zu wissen
pong
____________________________________
\"Ein Gewitter reinigt die Luft\", sagte der Mann, nachdem ein Blitz seine Frau erschlug Nicht klicken! Erstposteralarm/Beschwerde/Kummerkasten Verplattet |
![]() |
![]() |
![]() |
#3 |
Veteran
![]() |
![]() da es ein unter Linux laufendes Programm ist, verwendet es den g++ compiler.
#include <string.h> #include <malloc.h> #include <assert.h> #include <stdlib.h> #include <stdio.h> #include <ctype.h> #include "names.h" /*Funktionsnamespace zum Ordnen von Strings, bzw chars! *Struktur für Namen, enthält, den Namen, eine Zahl, und ein Pointer *nächsten namen! */ struct names { char *name; void *value; struct names *next; }; //Number Get, liefert einen Zeigen auf die Struktur zurück (über esten Parameter), void *nget(struct names *names, const char *name) { while (names) { //Array mit names Strukturen durch gehen, //wenn names ungleich names if (strcmp(name,names->name) == 0) //Wenn return names->value; else names = names->next; } /* For the moment we fail here to catch bugs */ /*fprintf(stderr,"nget(): Did not find '%s'\n",name);*/ return 0; } int nhas(struct names *names, const char *name) { while (names) { if (strcmp(name,names->name) == 0) return 1; else names = names->next; } return 0; } void ndef(struct names **names, const char *name, void *value) { struct names *n = malloc(sizeof(*n)); n->next = *names; n->value = value; n->name = malloc(strlen(name) + 1); strcpy(n->name,name); *names = n; } void nundef(struct names **names, const char *name) { struct names *n; while (*names) { if (strcmp(name,(*names)->name) == 0) { n = *names; *names = (*names)->next; free(n->name); free(n); return; } else { names = &((*names)->next); } } } void nmap(struct names *names, void (*fn)(const char *name, void *value)) { while (names) { fn(names->name,names->value); names = names->next; } } void nfree(struct names **names) { struct names *n; while (*names) { n = *names; *names = (*names)->next; free(n->name); free(n); } } void nwrite_str(struct names *names, FILE *target) { while (names) { fprintf(target,"\"%s\" \"%s\"\n",names->name,(char *)names->value); names = names->next; } } static void skip_ws(FILE *f) { int c; while (isspace(c = fgetc(f)) && (c != EOF)) {} ungetc(c,f); } /* * Skips #..., whitespace and respects double quotes * Returns NULL at EOF or error */ static char *next_token(FILE *f) { int c; static char token[256]; char *s; again: skip_ws(f); c = fgetc(f); ungetc(c,f); if (c == '"') { if (fscanf(f,"\"%[^\"\n]\"",token) != 1) return 0; } else if (c == '#') { if (fscanf(f,"%*[^\n]") != 0) return 0; goto again; } else { if (fscanf(f,"%[^# \n\t={}]",token) != 1) return 0; } s = malloc(strlen(token) + 1); strcpy(s,token); return s; } void nread_str(struct names **names, FILE *target) { char *name,*value; while ((name = next_token(target))) { value = next_token(target); if (!value) { fprintf(stderr,"nread(): Invalid input at end of file.\n"); return; } ndef(names,name,value); free(name); } } lg Etienne |
![]() |
![]() |
![]() |
#4 |
Hero
![]() Registriert seit: 04.09.2001
Beiträge: 894
|
![]() hi,
was ist daran ungewöhnlich? die funktion ist so deklariert, dass sie einen void pointer zurückliefern kann und genau das macht sie. beachte: void pointer != void es wird hier also einfach ein untypisierter zeiger retour gegeben - etwas "gefährlich", außer man weiß, was man macht. der fall "return 0" ist - zugegebenerweise etwas ungewöhnlich, aber durchaus möglich - es wird eine referenz auf die speicherstelle an adresse 0 retour geliefert. und genau hier wirds problematisch - der aufrufende der funktion erhält zugriff auf den speicher an stelle 0 und kann dort irgendwas reinschreiben - und das führt dann wohl früher oder später zum programmabsturz - einer sog. "memory access violation" eine typsichere programmiersprache wie z.B. C# würde soetwas nicht erlauben und bereits beim kompilieren einen fehler melden. fg -hannes |
![]() |
![]() |
![]() |
#5 | |
Elite
![]() |
![]() Zitat:
Code:
$> grep NULL /usr/include/linux/stddef.h #undef NULL #define NULL 0 #define NULL ((void *)0) Code:
return NULL; Code:
return 0; edit: ad typsichere sprachen. die speicheradresse 0 ist vom typ her eine gueltige adresse. der compiler schreit deswegen nicht.
____________________________________
Whoever built humanity left in a major design flaw: it was the tendency to bend at the knees. |
|
![]() |
![]() |
![]() |
#6 |
Hero
![]() Registriert seit: 04.09.2001
Beiträge: 894
|
![]() hi,
stimmt, es ist nicht ungewöhnlich NULL zurückzugeben - man schreibt dann für gewöhnlich aber auch NULL hin, nicht 0. Die tatsache, dass 0 durch NULL ersetzt wird (durch das define) erklärt eigentlich eh schon alles. ad typsichere sprachen: C#: unsafe void* fu1() { return 0; } Compilererror: error CS0266: Cannot implicitly convert type 'int' to 'void*'. An explicit conversion exists (are you missing a cast?) hingegen: unsafe void* fu1() { return null; } ========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped ========== fg -hannes |
![]() |
![]() |
![]() |
#7 |
Veteran
![]() |
![]() danke wieder was gelernt!
lg Etienne |
![]() |
![]() |
![]() |
Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1) | |
|
|