Frage

Kurz gesagt, ich möchte, dies zu tun:

const char **stringPtr = &getString();

Allerdings verstehe ich, dass man nicht auf & rvalues. Also ich bin mit diesem fest:

const char *string = getString();
const char **stringPtr = &string;

kann ich mit zwei Linien leben. Bin ich Probleme mit diesem Hack einzuführen? Ich sollte die Funktion keine Angst haben stringPtr ohnmächtig es in deklariert wird, nicht wahr?

Edit: Ich entschuldige mich für die ursprünglich nicht den vollständigen Kontext inklusive. Ich habe auf der Sommer-Projekt des Aufbaus eines Videospiels von Grund auf in C unter Verwendung von OpenGL für die Grafik gemacht. Ich lese Konfigurationsdaten aus einer Textdatei mit libconfig .

Eine der Komfortfunktionen für eine bestimmte Zeichenfolge aus der Konfigurationsdatei sieht wie folgt zu finden:

int config_setting_lookup_string(const config_setting_t *setting,
                                 const char *name, const char **value)
{
  config_setting_t *member = config_setting_get_member(setting, name);
  if(! member)
    return(CONFIG_FALSE);

  if(config_setting_type(member) != CONFIG_TYPE_STRING)
    return(CONFIG_FALSE);


  *value = config_setting_get_string(member);
  return(CONFIG_TRUE);
}

Die Art und Weise dieser Wert Mittel zugeordnet, dass, wenn Sie die Funktion eine nicht initialisierte value geben, versucht er nicht definiert Müll derefence, die so ziemlich immer macht mir eine segfault. Meine aktuelle Abhilfe für dieses Problem ist value auf einem anderen Zeiger zunächst initialisiert werden, etwa so:

const char *dummyPtr;
const char **fileName = &dummyPtr;
config_setting_lookup_string(foo, "bar", fileName);

Also habe ich, um herauszufinden, der beste Weg, ich versuche, den letzten Teil der Funktion neu zu schreiben, so dass ich nicht dieses zweistufigen Initialisierung durchführen. Ich dachte, dass die veränderte Funktion würde wie folgt aussehen:

int config_setting_lookup_string(const config_setting_t *setting,
                                 const char *name, const char **value)
{
  config_setting_t *member = config_setting_get_member(setting, name);
  if(! member)
    return(CONFIG_FALSE);

  if(config_setting_type(member) != CONFIG_TYPE_STRING)
    return(CONFIG_FALSE);

  const char *string = config_setting_get_string(member);
  value = &string;
  return(CONFIG_TRUE);
}
War es hilfreich?

Lösung

Von den zusätzlichen Informationen, so scheint es, was Sie versuchen ist, eine Funktion zu tun nennen, die eine Schnur durch eine der Funktionsargumente zurückkehren will. Der beste Weg, dies meiner Meinung nach tun, wäre so etwas wie:

const char* fileName;
config_setting_lookup_string(..., &fileName);
(...)
return fileName;

Dies wird Platz für ein const char * auf dem Stack zugeordnet werden. Der Funktionsaufruf wird der Zeiger mit der Adresse der Zeichenfolge füllen sie zurückkehren will. Dieser Zeigerwert kann dann bei Bedarf besteht aus der Funktion sein (im Gegensatz zu den Zeigern auf den Zeiger, der auf den Stapelpunkt wäre, und als ungültig, wenn die Funktion zurückkehrt). Beachten Sie, dass die Initialisierung Dateinamen mit „getString ()“ würde vermutlich ein Speicherleck, da der Zeiger auf die zurückgegebene Zeichenfolge überschrieben würde, und die Zeichenfolge nie freigegeben.

Andere Tipps

Wenn Sie eine Funktion aufrufen, die sind eine const char** benötigt, können Sie es wie folgt tun könnte:

const char *s = getString();
myFunction(&s);

Da s auf dem Stapel in dem obigen Beispiel zugeordnet ist, wenn Sie eine const char** von Ihrer Funktion zurückkehren wollen, müssen Sie es auf dem Heap setzen statt:

const char **sp = malloc(sizeof(const char *));
*sp = getString();
return sp;

HTH

string in Ihrem Fall ist eine lokale, so das Ermitteln der Adresse ist es eine schlechte Idee, da der Speicher für die lokale (und wird wahrscheinlich) wieder für andere Zwecke verwendet, wenn Sie die Methode verlassen. Im Allgemeinen ist es nicht eine gute Idee, um die Adresse einer lokalen Variablen außerhalb ihres Anwendungsbereichs zu verwenden.

Was wollen Sie erreichen?

Nein, Sie können nicht config_setting_lookup_string() in der Art und Weise ändern, die Sie beschrieben haben. Sie einen Zeiger auf die Variable string Rückkehr, aber sobald diese Funktion endet diese Variable Gültigkeitsbereich verlässt und zerstört wird.

Sie können jedoch beheben Ihr erstes Problem ganz leicht. Lassen Sie die Definition von config_setting_lookup_string() wie es ist, und nennen Sie es wie folgt:

const char *fileName = NULL;
config_setting_lookup_string(foo, "bar", &fileName);

Sie müssen die zwei Zeilen. Allerdings Zeichenfolge ist eine lokale Variable auf dem Stapel, sobald es Spielraum erlischt, können Sie nicht einen Zeiger auf die Daten, die von getString zurückgegeben haben ().

Ich mag nornagon und Caf-Lösung,

const char *fileName;
config_setting_lookup_string(foo, "bar", &fileName);

, aber wenn Sie config_setting_lookup_string ändern können Sie könnten auch es auf diese Weise tun:

int config_setting_lookup_string(..., const char *&value)
{
  ...
  const char *string = config_setting_get_string(member);
  value = string;
  ...
}

const char *fileName;
config_setting_lookup_string(foo, "bar", fileName);

Wenn Sie stringPtr zurückkehren, werden Sie einen Zeiger auf eine lokale Variable Rückkehr (string). Also nein, man kann das nicht tun.

Warum versuchen Sie, dies zu tun? Das könnte uns erlauben, bessere Vorschläge zu machen.

Update: Okay, jetzt sehe ich, was Sie versuchen zu tun. Sie tun es falsch:

value = &string;

Wenn value als Ausgabeparameter gemeint ist, die über die Linie kann nicht funktionieren, weil Sie zu einem lokalen Variablen zuweisen .

Lassen Sie sich nicht die zusätzliche Dereferenzierungsebene Sie verwirren. Wenn Sie eine Funktion geschrieben haben, die einen Ausgabeparameter des Typs T hatte, würden Sie schreiben es als:

void foo(T* value)
{
    *value = GetT();
}

Jetzt ersetzen T mit const char*:

...
*value = string;
...

Und jetzt bist du keine temporäre, lokale Variablen beteiligt sind. Das ist natürlich, wie der Code wurde ursprünglich geschrieben (und dass ein Teil davon richtig war), so dass nicht wirklich Ihnen helfen. Um richten Sie Ihre Absicht, sollten Sie:

  1. Make config_setting_lookup_string tun assert(value != NULL).
  2. Prüfung werden die Anrufer der Funktion und befestigen Sie sie vorbei Müll zu stoppen. Sie sollten tun:

    const char * foo; config_setting_lookup_string (..., & foo);

und NICHT:

const char** foo;
config_setting_lookup_string(..., foo);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top