void **mar_init(...), float **f; --> WTF
-
Kann mir bitte mal erklären was zwei Sternchen hintereinander zu bedeuten haben, zum einen bei einer Variablendeklaration wie etwa:
float **f;
und zum anderen bei Funktionen wie etwa
void ** mat_init(...)
Vielen Dank
-
CrazyOwl schrieb:
Kann mri bitte mal erklären was zwei Sternchen hintereinander zu bedeuten haben, zum einen bei einer Variablendeklaration wie etwa:
type i;
i ist vom Typ type
type* i;
i ist ein Zeiger auf ein Objekt vom Typ typeNehmen wir jetzt an type ist ein char* - alles klar?
-
Ok, also ein Pointer auf einen Pointer, für was brauch ich so was jetzt ?
Und besonders frag ich mich das bei der void ** - Funktion die ja an und für sich ncihts zurückgibt oder ?Und was bedeuted das jetzt genau bezogen auf float** f; ?
Danke
-
CrazyOwl schrieb:
Ok, also ein Pointer auf einen Pointer, für was brauch ich so was jetzt ?
Für das selbe wie du einen 'normalen' Zeiger brauchst...
Und besonders frag ich mich das bei der void ** - Funktion die ja an und für sich ncihts zurückgibt oder ?
Keine Ahnnung. Musst du doku lesen...
Und was bedeuted das jetzt genau bezogen auf float** f; ?
Ein Zeiger auf einen Zeiger auf ein float.
Kleines Beispiel:
int safe_realloc(void** p, size_t size) { void* tmp=realloc(p, size); if(!tmp) return 1; *p=tmp; return 0; }
-
CrazyOwl schrieb:
Jaja Pinter is klar, mit einem Sternchen is alles verständlich aber für was brauch ich 2 Sternchen hintereinander ? Besonders frag ich mich das bei einer void-Funktion, die ja an und für sich nichts zurückgibt oder ?
Typ <- *Typ <- **Typ
**Variable ist ein Zeiger auf einen Zeiger der auf "Typ" zeigt.
Und die "void-Funktion" gibt schon was zurück
void* func(); // gibt einen Voidpointer zurück void func(); //gibt tatsächlich nichts zurück
z.B. malloc()
Edit: zu langsam...
-
Eine void*-Funktion gibt nicht Nichts zurück, sondern einen Void-Pointer. Das ist ein Pointer, der auf eine einzelne Adresse zeigt, aber keine "Größe" hat. Somit kann man ihn auch nicht dereferenzieren. Ich würde mal sagen, dass man einen Doppel-Voidpointer also erstmal konvertieren müsste, um einmal dereferenzieren zu können um an die 2. Adresse zu kommen.
Ein float-Doppelpointer könnte zum Einen benutzt werden, um ein 2-dimensionales dynamisches Array "darzustellen", oder wenn du die Adresse von dem Pointer in einer Funktion, der der Pointer als Argument übergeben wurde geändert werden muss. Dies wäre sonst nicht möglich, da die Adresse eines Pointers wie bei jeder anderen Variablen by-value übergeben wird.
-
masterofx32 schrieb:
Ein float-Doppelpointer könnte zum Einen benutzt werden, um ein 2-dimensionales dynamisches Array "darzustellen"
Das könnte hinkommen, denn die Aufgabe ist es eine Matrix einzulesen. Dazu wird als erstes angegeben wie viele Elemente diese Matrix hat (quadratisch) und diese sollen dann in einem Array gespeichert werden, kann mir bitte noch wer einen Tipp geben wie man das realisieren könnte, ich steh im Moment leider total daneben und die Suchen Funktion will auch nicht so recht.
Danke
-
Hat sich alles erledigt, vielen Dank für die hilfreichen Tipps.
-
void** macht doch gar keinen sinn, oder übersehe ich da was?
-
Ja, void-Pointer != void.
-
DrGreenthumb schrieb:
void** macht doch gar keinen sinn, oder übersehe ich da was?
Wie übergibst du einen void* denn sonst by reference?
Oder wenn wir von generischen Funktionen ausgehen, die nehmen oft nen void* als Param, da kann man leicht void** haben. Sehe da kein 'Sinn'-Problem. Oft vorkommen tut es allerdings nicht.
-
DrGreenthumb schrieb:
void** macht doch gar keinen sinn, oder übersehe ich da was?
ich glaub auch. 'void*' (nur ein sternchen) reicht
-
Shade Of Mine schrieb:
DrGreenthumb schrieb:
void** macht doch gar keinen sinn, oder übersehe ich da was?
Wie übergibst du einen void* denn sonst by reference?
ja stimmt, hatte nen denkfehler
-
DrGreenthumb schrieb:
void** macht doch gar keinen sinn, oder übersehe ich da was?
wieso soll das kein Sinn machen? Ein Doppelpointer auf etwas unbekanntes.
rex@supertux:~/tmp> cat s.c #include <stdio.h> void p(void** b) { printf("%s\n", *b); } int main(void) { char* x = "Hello World"; p((void**) &x); return 0; } rex@supertux:~/tmp> gcc s.c -osc -ansi rex@supertux:~/tmp> ./sc Hello World
Ich hab sowas auch nie gesehen, aber so geht es, der Compiler meckert nicht einmal. Ich glaube, es gibt einfach keine Verwendung dafür
-
DrGreenthumb schrieb:
void** macht doch gar keinen sinn, oder übersehe ich da was?
ist mir nur einmal begegnet, daß ich void** schreiben wollte:
class Memory { public: enum{PAGESIZE=8192,FRAGMENTATION=65536}; private: void *freePage; public: Memory(void) { freePage=NULL; }; ~Memory(void) { }; void grow(void) { char *p=(char*)VirtualAlloc( NULL, FRAGMENTATION, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE ); for(int i=0;i<FRAGMENTATION/PAGESIZE;i++) { free(p); p+=PAGESIZE; }; }; void *alloc(void) { if(freePage==NULL) { grow(); } void *result=freePage; freePage=*(void**)freePage; // cout<<"alloc "<<result<<'\n'; return result; }; ...
-
"void**" wird sogar sehr haeufig verwendet, wenn eine Funktion einen oder mehrere "void*" zurueckliefern muss, der Return-Wert aber schon von einem Error-Code z.B. vorbelegt ist (z.B. bei API-Funktionen):
typedef int ApiError; ApiError API_AllocBuffers( void* Context_Handle, size_t size, void** buf1, void** buf2 );
verwendet wird das dann z.B. so:
bool init1( void* context ) { ApiError err; void* buf1 = 0; void* buf2 = 0; err = API_AllocBuffers( context, sizeof( XYZ ), &buf1, &buf2 ); if ( err != APIERR_OKAY ) return false; /* ... */ return true; }
-
Power Off schrieb:
"void**" wird sogar sehr haeufig verwendet, wenn eine Funktion einen oder mehrere "void*" zurueckliefern muss, der Return-Wert aber schon von einem Error-Code z.B. vorbelegt ist (z.B. bei API-Funktionen):
welche api macht das so?
-
volkard schrieb:
welche api macht das so?
z.B. COM- und OLE-APIs in Windows, wie z.B. QueryInterface(), meine eigenen Libraries, die ich auf der Arbeit oder zu Hause entwickelt habe, usw. -- oder CORBA, z.B.
Es gehoert zum sauberen API-Design, dass APIs, die einen Error-Code zurueckliefern, dies konsequent z.B. ueber den Rueckgabewert tun. Andere Rueckgabewerte muessen dann in C++ als Referenz, in C als Pointer-to-X an die API-Funktion als InOut-Parameter uebergeben werden.
Pointer sind ja die einzige Moeglichkeit, in C bei einem Call einen Pass-By-Reference von Argumenten zu machen.
Hat man jetzt ein Pass-By-Reference eines Zeigers, kommen zwangslaeufig "X**" ins Spiel. Das laesst sich gar nicht verhindern.
Dafuer gibt's solche Konstruktionen in C ja. Sogar der Parameter von main(), argv, ist vom Typ "char**", also nutzt fast jedes C Programm Pointer-To-Pointer.
"X***" hingegen oder "X****" werden seltener verwendet, kommen aber gelegentlich vor.
-
Power Off schrieb:
Pointer sind ja die einzige Moeglichkeit, in C bei einem Call einen Pass-By-Reference von Argumenten zu machen.
jo, aber es reicht ein einfacher void*, weil der schon eine adresse beinhaltet, die auf alles mögliche zeigen kann. auch auf andere pointer oder pointer auf pointer usw. bei void* ist mehrfache indirektion echt überflüssig
-
void** als Parameter ist ja verständlich, aber was bringt einem denn ein Doppel-Voidpointer als Rückgabewert?
-
net schrieb:
jo, aber es reicht ein einfacher void*, weil der schon eine adresse beinhaltet, die auf alles mögliche zeigen kann. auch auf andere pointer oder pointer auf pointer usw. bei void* ist mehrfache indirektion echt überflüssig
Das fuehrt dazu, dass auf beiden Seiten (beim Caller und bei der API-Funktion) dann bloedsinnige Casts erforderlich sind:
void apifunc( void* arg ) { *((void**)arg) = allocate_it(); } void caller( void ) { void* ptr = 0; apifunc( (void*)(&ptr) ); }
waehrenddessen "void**" viel sauberer und leicher verstaendlich ist:
void apifunc( void** arg ) { *arg = allocate_it(); } void caller( void ) { void* ptr = 0; apifunc( &ptr ); }
klaro?