Frage

Ich schreibe eine Zugriffsfunktion, die einen Zeiger auf einen internen Puffer zurück, und ich möchte den Nutzern meiner Funktion anzudeuten, dass sie sollte das Objekt nicht aktualisieren, die darauf ist. Ein sehr konstruiertes Beispiel wäre:

void myAccessFunc(bool string, void* p, size_t* len)
{
  static const char* s = "aha!";
  static const int i = 123;

  if (string) {
     *(char**)p = &s;
     *len = strlen(s);
  }
  else {
     *(int**)p = &i;
     *len = sizeof(i);
  }
}

char* s;
size_t bytes;
myAccessFunc(true,&s, &bytes);
printf("Got '%s'\n", s);

Ja, ich weiß, das sieht flakey.

Was ich verhindern will, ist:

char* s;
size_t bytes;
myAccessFunc(true,&s,&bytes);
s[4] = '?';

Ich weiß, ich kann es nicht vollständig verhindern, aber ich würde zumindest wie der Compiler-Warnung an einen Benutzer anzudeuten, dass sie sollten nicht so tun. Wenn sie meinen Zeiger werfen, dann ist das ihr Problem. Gibt es eine Kombination von const und nichtig und *, die dies tun? Ich habe versucht, so etwas wie:

void myAccessFunc(bool string, const void** p, size_t* len);

, aber es schien mit der Leerheit des Zeigers abschaffen, so hatte ein Anrufer zu tun:

const void* p;
size_t bytes;
myAccessFunc(true, &p, &bytes);

oder

const char* s;
size_t bytes;
myAccessFunc(true, (const void**)&s, &bytes);

und konnte nur noch:

const int * ip;
const char* s;
size_t bytes;
myAccessFunc(true, &s, &bytes);
myAccessFunc(false, &i, &bytes);

Ich kam schließlich um an:

const void* myAccessFunc(bool string, size_t* len);

und wenn der Benutzer tut:

char* p = myAcccessFunc(true,&bytes);

Der Compiler (GCC, zumindest), beschwert sich über die Qualifikation Wegwerfen.

War es hilfreich?

Lösung

Am besten wäre es so etwas wie zu tun:

const void * myAccessFunc();

Wenn Sie den Zeiger auf die Interna zurückkehren, das ist ein bisschen natürliche, als sie als out-Parameter übergeben.

Wenn Sie es als out-Parameter zu übergeben, würden Sie wollen:

void myAccessFunc(const void **p);

, die verhindert, dass sie dies versehentlich tun:

void *p;  /* error: must be 'const void *p;' */
myAccessFunc(&p);

Andere Tipps

Sie haben zwei Dinge, die Sie tun können:

  • Zurück a const void *
  • eine Dokumentation für die API schreiben die Benutzer sagen, nicht den Rückgabewert
  • ändern

Mit dieser sagte, jeder API Benutzer, der mit einem Zeiger, so zu versuchen und Dreck entscheidet verdient, was sie bekommen. P

zu verhindern, ist nicht möglich, da Sie Konstantheit wegzuwerfen können. Wenn Sie Ihre Funktionsparameter const machen, werden Sie es werfen müssen, um sich innerhalb der Funktion entfernt. Sie würde auch jemand mit Ihrer Funktion liegen und könnte jede Menge Spaß Fehler verursachen.

Sie könnten versuchen, stattdessen einen Zeiger zurück. Dann dest würden Sie auf keinen eigenen konst verletzen. Das kann allerdings nicht in diesem Fall angemessen sein.

einen Zeiger Rückkehr wäre am besten, aber wenn Sie absolut müssen sie einen out-Parameter machen, können Sie eine Struktur als Vermittler verwenden:

typedef struct _ptr_holder {
   const void* ptr;
} ptr_holder;

void myAccessFunc( bool string, ptr_holder* ptr ) {
...
}

ptr_holder s;
myAccessFunc(true,&s);
printf("Got '%s'\n", s.ptr);

Es ist kitschig, aber es sollte den Trick

So Sie Modifikation über den Zeiger verhindern möchten Sie zurückkommen? Versuchen Sie folgendes:

const void* myAccessFunc(bool string);

Was ist daran falsch? Wenn Sie eine gültige Antwort stimmen nach unten gehen, lassen Sie einen Kommentar.

Wenn Sie eine C-Bibliothek schreiben, wo Sie nicht wollen, einige interne Datenstruktur belichten es gut sein kann, einen zusätzlichen Weg zu gehen und versteckt Implementierung mit einem nicht spezifizierten struct typedef. Dies ist auch eine undurchsichtigen Typen

genannt

Beispiel:

In my_interface.h

 #ifndef __MYINTERFACE_H__
 #define __MYINTERFACE_H__

 /* The unspecified struct statement */
 typedef struct s_my_data t_my_data;

 t_my_data  *new_my_data(int someInitializer);
 void        free_my_data(t_my_data *data);
 int         enter_my_data(t_my_data *data, int someDataToEnter);

 const char *return_str_my_data(t_my_data *data);

 #endif /* __MYINTERFACE_H__ */



In my_interface.c

 #include <my_interface.h>

 /* Keep struct in .c file */
 struct s_my_data {
     int    length;
     char  *string;
 };

 t_my_data *new_my_data(int someInitializer)
 {
     /* the exercise */
 }

 void free_my_data(t_my_data *data)
 {
     /* the exercise */
 }

 int enter_my_data(t_my_data *data, int someDataToEnter)
 {
     /* the exercise */
 }

 const char *return_str_my_data(t_my_data *data)
 {
     /* the exercise */
 }

Ist das C oder C ++? Warum in dem int Fall sind vorbei Sie den Zeiger auf einen statischen const? Die Schnittstelle ist suspekt.

Überlast- und erhält von der boolean in der Schnittstelle los:

void myAccessFunc( const char* * const p, size_t* len){
   *p = "blahblahblah";
   *len = 12;
}

void myAccessFunc( const int* * const ppI, size_t* len){
   static const int i = 123;
   *ppI = &i;
   *len = 4;
}

wird zu der Prüfung befreien. Da der Benutzer für die ursprüngliche Funktion wahr oder falsch kennt, weiß er, welche zu benutzen. Starke Typisierung ist dein Freund. Beseitigt der Klasse von Fehlern in dem Art und Zeiger inkonsistent sind ...

BTW vorbei solche Steuerflags gegen Überlastung unerwünscht ist, besonders in kleinen Methoden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top