Unklare Compilerfehlermeldung
-
Hi!
Ich hab folgendes bisschen Code geschrieben:
Header-Dateivoid gibbsSampling( int timeSeriesData[StatisticsObject::number30MinIntervals][StatisticsObject::numberOfDays], int trows, int tcols, double probs[(StatisticsObject::number30MinIntervals+1)][StatisticsObject::numberOfDays], int prows, int pcols, int numOfIterations, int numOfIterationsToSkip );StatisticsObject::number30MinIntervals
StatisticsObject::numberOfDayssind statische Konstanten aus einer anderen Headerdatei.
CPP Datei
void GibbsSampler::gibbsSampling( int timeSeriesData[StatisticsObject::number30MinIntervals][StatisticsObject::numberOfDays], int trows, int tcols, double probs[(StatisticsObject::number30MinIntervals+1)][StatisticsObject::numberOfDays], int prows, int pcols, int numOfIterations, int numOfIterationsToSkip )Die Methode rufe ich wie folgt auf:
RandomNumberGenerator rng; GibbsSampler gs( &rng ); int ts[(StatisticsObject::number30MinIntervals)][StatisticsObject::numberOfDays]; int p[(StatisticsObject::number30MinIntervals+1)][StatisticsObject::numberOfDays]; gs.gibbsSampling( ts, 48, 7, p, 49, 100, 1000, 900 );Erhalte aber folgenden Fehler:
g++ -g -Wall -c DDoS.cpp -o DDoSS.o
DDoS.cpp: In function ‘int main()’:
DDoS.cpp:38: error: no matching function for call to ‘GibbsSampler::gibbsSampling(int [2][2], int, int, int [3][2], int, int, int, int)’
GibbsSampler.h:12: note: candidates are: void GibbsSampler::gibbsSampling(int ()[2], int, int, double ()[2], int, int, int, int)
make: *** [DDoSS.o] Error 1Mir erschließt sich aus der Fehlermeldung leider keine Lösung.
-
Du versuchst, ein zweidimensionales int-Array in ein zweidimensionales double-Array zu quetschen. Mit
double /* <-- */ p[(StatisticsObject::number30MinIntervals+1)][StatisticsObject::numberOfDays];müsste es gehen.
-
Ach Gott!
Danke!
-
Ich hab noch eine weitergehende Frage zur Übergabe von Funktionswerten.
Ich habe meine Methode jetzt wie folgt deklariert:
Header Dateivoid gibbsSampling( int** timeSeriesData, int trows, int tcols, double** probs, int prows, int pcols, int numOfIterations, int numOfIterationsToSkip );und ich rufe sie so auf:
RandomNumberGenerator rng; GibbsSampler gs( &rng ); int ts[(StatisticsObject::number30MinIntervals)][StatisticsObject::numberOfDays]; double p[(StatisticsObject::number30MinIntervals+1)][StatisticsObject::numberOfDays]; gs.gibbsSampling( ts, 48, 7, p, 49, 100, 1000, 900 );Dann sagt mir der Compiler folgendes:
g++ -g -Wall -c DDoS.cpp -o DDoSS.o
DDoS.cpp: In function ‘int main()’:
DDoS.cpp:38: error: no matching function for call to ‘GibbsSampler::gibbsSampling(int [2][2], int, int, double [3][2], int, int, int, int)’
GibbsSampler.h:14: note: candidates are: void GibbsSampler::gibbsSampling(int**, int, int, double**, int, int, int, int)
make: *** [DDoSS.o] Error 1Mir ist das nicht ganz klar, weil meinem Wissen nach ein 2-dimensionales Array doch auch als double** oder int** deklariert werden kann. Insofern müsste es doch passen wenn ich die Methode so aufrufe. Warum geht das trotzdem nicht?
-
Ein statisch Array mit der Länge 2 ist nicht Typegleich mit der Länge 2+1.
-
Versteh ich nicht. Die Antwort ist zu kurz.
-
Kompilier mal:
void doit(int x[3][3]) { } int main() { int a[3][2]; doit(a); return 0; }
-
Ich sehe jetzt nicht wieso das meine Frage beantworten soll.
Meiner Ansicht nach ist es völlig egal was für ein Array ich übergebe. Meine Methodendklaration sieht ja auch nicht so aus wie in deinem Beispiel. Mein Problem wäre das hier:
void doit(int** x) { } int main() { int a[3][2]; doit(a); return 0; }macht meiner Meinung nach das gleiche wie
void doit(int** x) { } int main() { int a[67][100]; doit(a); return 0; }a ist doch ein 2-Dimensionaler Pointer.
-
HändyÄndy schrieb:
void doit(int** x) { } int main() { int a[67][100]; doit(a); return 0; }Ein Zeiger ist etwas anderes als ein Array. Es ist zwar richtig, dass ein Array beim Aufruf einer Funktion sich als ein Zeiger auf sein erstes Element ausgibt, hier ist dies jedoch ein Zeiger auf auf einen int[100]. Und eben nicht ein Zeiger auf einen Zeiger. Und deshalb passt dies nicht zusammen.
-
Achso. Okay, ich hab meinen Aufruf jetzt einfach modifiziert und rufe sie jetzt so auf:
gs.gibbsSampling( (int**) ts, 48, 7, (double**) p, 49, 100, 1000, 900 );Kappt auch, finde ich allerdings jetzt nich besonders logisch, dass man das casten muss. Naja...
Vielen Dank für die hilfreichen Antworten.
-
Ich habe mir mal erlaubt die code-tags durch cpp-tags zu ersetzen und den code neu zu formatieren...
HändyÄndy schrieb:
void gibbsSampling( int** timeSeriesData, int trows, int tcols, double** probs, int prows, int pcols, int numOfIterations, int numOfIterationsToSkip );und ich rufe sie so auf:
RandomNumberGenerator rng; GibbsSampler gs( &rng ); int ts[...][...]; double p[...][...]; gs.gibbsSampling( ts, 48, 7, p, 49, 100, 1000, 900 );HändyÄndy schrieb:
Mir ist das nicht ganz klar, weil meinem Wissen nach ein 2-dimensionales Array doch auch als double** oder int** deklariert werden kann. Insofern müsste es doch passen wenn ich die Methode so aufrufe. Warum geht das trotzdem nicht?
Weil Du Dich geirrt hast. Ein Zeiger auf ein Zeiger auf int (p) ist nicht dasselbe wie ein Zeiger auf ein Array aus ints (q), siehe unten.
int a[2] = {1,2}; p x a y int b[2] = {3,4}; [.]-->[.]-->[1] q +---+ int *x[2] = {&a[0],&b[0]}; [.] [2] [.]-->|[1]| int y[2][2] = { \ |[2]| {1,2}, \ b +---+ {3,4}, >[3] |[3]| }; [4] |[4]| int **p = x; +---+ int (*q)[2] = y;Hier symbolisiert "." eine Speicheradresse. Die Elemente des y-Arrays sind wiederum Arrays.
kk
-
HändyÄndy schrieb:
gs.gibbsSampling( (int**) ts, 48, 7, (double**) p, 49, 100, 1000, 900 );Kappt auch, finde ich allerdings jetzt nich besonders logisch, dass man das casten muss. Naja...
Wenn Du mit "Klappt auch" meinst, dass es kompiliert, dann ja. Wenn Du damit meinst "Es tut das, was ich will", nein, tut es nicht. Das ist ein ReinterpretCast. Hier sagst Du dem Compiler: "Hey, ich weiß es besser, also halt die Schnauze". Aber Du weißt es nicht besser. Also lass die Finger davon. Es funzt eh nicht.
-
Vielleicht Boost::Matrix verwenden?
-
Zeus schrieb:
Vielleicht Boost::Matrix verwenden?
Das würde ein wenig verschleiern, aber es rettet
gs.gibbsSampling( ts, 48, 7, p, 49, 100, 1000, 900 );auch nicht.

-
HändyÄndy schrieb:
void doit(int** x); int main() { int a[67][100]; doit(a); return 0; }a ist doch ein 2-Dimensionaler Pointer.
a ist ein Array aus Arrays und kein Zeiger. Und so etwas wie "zweidimensionale" Zeiger gibt es nicht. Es gibt aber Zeiger auf Zeiger. Du müsstest korrekterweise doit so deklarieren:
void doit(int x[67] [100]); void doit(int x[123][100]); void doit(int x[] [100]); void doit(int (*x) [100]);(ist alles äquivalent)
Die Geschichte der Menstru ... ähm... Zeiger und Arrays ist eine Geschichte voller Missverständnisse. Arrays sind keine Zeiger. Bei Parametertypen findet aber eine Transformation statt; denn Arrays kann man nicht "per value" übergeben. Wird ein Funktionsparameter mit dem Typ T[] oder T[N] deklariert, wird daraus automatisch ein T*. Das ist aber nur auf der obersten Ebene so. Das heißt dass ein int[2][2] zu einem int(*)[2] wird und auf der Aufruferseite ein "array-to-pointer" decay stattfindet.
kk
-
volkard schrieb:
Zeus schrieb:
Vielleicht Boost::Matrix verwenden?
Das würde ein wenig verschleiern, aber es rettet
gs.gibbsSampling( ts, 48, 7, p, 49, 100, 1000, 900 );auch nicht.

void gibbsSampling( int timeSeriesData[StatisticsObject::number30MinIntervals][StatisticsObject::numberOfDays], int trows, int tcols, double probs[(StatisticsObject::number30MinIntervals+1)][StatisticsObject::numberOfDays], int prows, int pcols, int numOfIterations, int numOfIterationsToSkip );Auf Boost Matrix umsteigen, bedeutet, da fallen 4 Parameter weg.
trows, tcols, prows, pcols

-
Zeus schrieb:
Auf Boost Matrix umsteigen, bedeutet, da fallen 4 Parameter weg.
trows, tcols, prows, pcols
Ups, schnell umsteigen!
-
Meinst Du multi_array? Ja, könnte man machen.
Ich habe mir so etwas ähnliches wie Iteratoren für beliebig-dimensionale Daten gebastelt (aber immer noch ein "rechteckiges Gitter") und benutze das gerne. Wenn's einen interessiert, versuche ich mal das Konzept durch ein Anwendungsbeispiel zu konkretisieren:
template<typename Navigator> typename enable_if<(Navigator::dimensions == 2), void>::type show(Navigator nav) { const int width = nav.size(0); // 1st dimension const int height = nav.size(1); // 2nd dimension const auto right = nav.make_offset(make_point(1,0)); for (int y=0; y<height; ++y) { auto locator = nav.get_locator(make_point(0,y)); for (int x=0; x<width; ++x) { std::cout << ' ' << *locator; locator += right; } } }Ein Navigator ist vergleichbar mit pair<Iterator,Iterator>. Ein Locator wäre der Iterator. Aber Statt ++ und -- unterstützt er += und -= in Verbindung mit einem "Offset", welcher keine Ganzzahl sein muss. Da ich aber vorwiegend ein lineares Memorylayout benutze, ist ein Locator i.d.R. ein Zeiger und Offsets vom Typ ptrdiff_t.
kk