Ergebnis 1 bis 5 von 5

Thema: [C++] Seltsame Fehler beim Initialisieren eines const double* Parameters mit Array

  1. #1

    [C++] Seltsame Fehler beim Initialisieren eines const double* Parameters mit Array

    Hallo Freunde des Programmiertums.

    Bei meiner Arbeit an einem Projekt bin ich ueber einige seltsame Fehler gestossen.
    Anscheinend ist es nicht ohne weiteres moeglich, einen const double* Parameter mit einem temporaeren Array zu initialisieren. Selbst das casten eines solchen, stellt sich vielmehr als Krankheit denn als Heilung dar, da der gcc 4 dies zwar unter Umstaenden unterstuetzt, der gcc 3 sich allerdings ueber den selben Code beschwert.

    Hier ein kleiner Quelltext, der das Problem verdeutlichen soll. Die Fehlermeldungen der Compiler stehen in den Kommentaren und gelten fuer jede Zeile des folgenden Blocks erneut.

    Code:
    #include <iostream>
    
    using namespace std;
    
    void foo( size_t num, const double* arr) {
      if (!arr) return;
      for (size_t i=0; i<num; ++i) {
        cout << arr[i] << " ";
      }
      cout << endl;
    }
    
    int main(int argc, char** argv) {
    
      double X = 1.0, Y = 2.0, Z = 3.0;
    
      // gcc 3.4 and 4.3: error: expected primary-expression before '{' token
      foo(3, {X, Y, Z});
      foo(3, {1.0, 2.0, 3.0});
    
    
      // gcc 3.4 error: initializer for scalar variable requires one element
      // gcc 4.3 error: too many initializers for 'double*'
      // gcc 4.3 error: cannot convert 'double' to 'double*' in initialization
      foo(3, (double*) {X, Y, Z});
      foo(3, (double*) {1.0, 2.0, 3.0});
    
    
      // gcc 3.4 error: invalid use of non-lvalue array
      // but works in gcc 4.3
      foo(3, (double[]) {X, Y, Z});
      foo(3, (double[3]) {X, Y, Z});
    
    
      // works in gcc 3.4 and 4.3
      foo(3, (double[]) {1.0, 2.0, 3.0});
      foo(3, (double[3]) {1.0, 2.0, 3.0});
    
      return 0;
    }
    Eigentlich sollte in allen Faellen der Compiler ein temporaeres Array mit 3 Elementen vom Typ double erstellen, selbiges als const Pointer uebergeben, die Funktion ausfuehren und das temporaere Array hinterher vernichten, sobald es Out of Scope geht. Tut er aber in den seltensten Faellen. Anscheinend versteht er nicht, dass {1.0, 2.0, 3.0} bzw {X, Y, Z} ein double array sein soll.

    Normalerweise nimmt der Compiler problemlos den cast von einem Array auf einen Pointer vor, aber hier versteht er nicht, was ich von ihm will. Auch ein direkter cast nach double* ist nutzlos, da er anscheinend wieder mit dem Array nicht klar kommt. Ich will ja gerade nicht eine skalare Variable vom Typ double initialisieren.

    Ein Expliziter Cast des Arrays {X, Y, Z} nach double[3] (und sogar allgemeiner nach double[]) schafft wenigstens beim gcc 4 Abhilfe, der gcc 3 ist allerdings nach wie vor ueberfordert. Im Falle des gcc 4 liefert der ausfuehrbare Code sogar das korrekte Ergebnis "1 2 3". Warum der gcc 3 der Meinung ist, ich wuerde hier eine illegale Operation mit einem Non-L-Value durchfuehren, ist mir allerdings schleierhaft. Und das es ein Non-L-Value ist, sollte doch klar sein, denn schliesslich habe ich keinerlei Absicht, auf dem temporaeren Array herum zu schreiben, warum sollte ich auch, schliesslich ist es doch ein const double*. Und Lesen sollte keine illegale Operation sein.

    Der gcc 3 hingegen laesst sich erst von der Richtigkeit des Codes ueberzeugen, wenn ich statt den Variablen Literale einfuege oder X, Y und Z als const double deklariere. Warum ist mir unbekannt, denn immerhin sollte das Array {X, Y, Z} schliesslich genau so const sein. Selbst ein Cast wie (const double[]) {X, Y, Z} stimmt ihn aber nicht um.

    Natuerlich kann man anfuehren, warum ich ueberhaupt einen const double* in der Funktion verwende, wo es doch const double[] gibt (der Unterschied zum const double* ist allerdings nur subtil). Dachte ich mir auch, nur aendert sich das Problem dadurch kein Stueck: Ich bekomme auch bei const double[] als Parameter von foo die exakt gleichen Fehlermeldungen und Verhaltensmuster.

    In meinem Projekt, wo ich so etwas einsetzen will, ist es sogar noch eine Idee schlimmer, weil ich dort keinen gewoehnlichen Funktionsaufruf habe, sondern eine Initialisierung in einem Constructor vornehme. Vom Prinzip her sollte dies aber kaum etwas aendern.

    Weiss vielleicht einer, ob ich etwas Grundlegendes einfach falsch verstanden habe ? Ich weiss schon, dass das Problem eigentlich die Muehe nicht wert ist, aber dennoch aergert es mich schon eine ganze Weise, denn bisher hatte ich eigentlich angenommen, die Sprache C++ halbwegs passabel zu beherrschen, doch anscheinend uebersehe ich hier etwas Fundamentales.

    Gruss Luki

    Geändert von Ineluki (04.04.2011 um 16:11 Uhr)

  2. #2
    Disclaimer: Ich habe C++ nie gelernt und verabscheue es. Aber mein Tipp wäre, dass dem Compiler const double* arr nicht weit genug geht – funktioniert es vielleicht mit const double* const arr (oder einer äquivalenten Alternative) besser?
    Wie gesagt, bloß geraten, da ich diese bescheuert aussehende Syntax schon öfter gesehen habe und sie ja zu irgendwas gut sein muss.

  3. #3
    Ist ’ne Weile her, aber ich meine, dass const double* foo heißt, dass der Pointer konstant ist, double * const foo, dass die Zahl selber konstant ist, und const double * const foo, dass beides konstant ist.

  4. #4
    Nette Idee, aber auch mit const double* const geht es nicht.

  5. #5
    Zitat Zitat von mq Beitrag anzeigen
    Ist ’ne Weile her, aber ich meine, dass const double* foo heißt, dass der Pointer konstant ist, double * const foo, dass die Zahl selber konstant ist, und const double * const foo, dass beides konstant ist.
    Laut schneller Recherche scheint's genau andersrum zu sein.
    Aber gut, nachdem's eh nichts geholfen hat, ist das wohl für den gegenständlichen Fall auch egal. :-/

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •